Skip to content
Template Literal Types
step 1/5

Reading — step 1 of 5

Learn

~1 min readType-Level Programming

Template literal types let you compose string literal types using template syntax. Compile-time string manipulation.

type Greeting = `hello, ${string}`;

const a: Greeting = 'hello, world';     // OK
const b: Greeting = 'hi there';          // Error

The placeholder can be specific:

type Color = 'red' | 'green' | 'blue';
type HexColor = `#${string}`;
type CssVariable = `--${string}`;

type EventName = `on${Capitalize<string>}`;
const evt: EventName = 'onClick';        // OK

Combinatorial expansion — string unions multiply:

type Verb = 'get' | 'set' | 'delete';
type Resource = 'user' | 'post' | 'comment';
type Action = `${Verb}_${Resource}`;
// 'get_user' | 'get_post' | 'get_comment' | 'set_user' | ... (9 combinations)

Built-in string transformations:

  • Uppercase<T>, Lowercase<T>
  • Capitalize<T>, Uncapitalize<T>

Pattern matching with infer in template types:

type HttpMethod<T> = T extends `${infer M} ${string}` ? M : never;

type A = HttpMethod<'GET /users'>;       // 'GET'
type B = HttpMethod<'POST /api'>;        // 'POST'

The infer M captures the part before the space.

Practical use case — typed event names:

type EventMap = {
    click: { x: number; y: number };
    hover: { id: string };
    keyup: { key: string };
};

type Handler<E extends keyof EventMap> = (event: EventMap[E]) => void;

function on<E extends keyof EventMap>(name: E, handler: Handler<E>) {
    // ...
}

on('click', e => console.log(e.x, e.y));     // typed
on('hover', e => console.log(e.id));         // typed
on('unknown', () => {});                      // ERROR — not a key

Combined with key remapping — type-safe APIs:

type Getters<T> = {
    [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
};

type UserGetters = Getters<{ name: string; age: number }>;
// { getName: () => string; getAge: () => number }

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…