Template Literal Types & Key Remapping
In one line
Template literal types let the type system build and destructure string literals, which turns conventions like onClick or /users/:id into things the compiler can check.
What it is
The syntax mirrors runtime template strings: type Greeting = `hello ${string}`. Combined with unions it multiplies out — `${'get'|'set'}${Capitalize<'name'|'age'>}` produces four literal types. That cross-product is the mechanism behind typed event names, CSS property unions, and generated API surfaces.
Four intrinsic helpers come with it: Uppercase, Lowercase, Capitalize, and Uncapitalize. They exist precisely because naming conventions in JavaScript are case transformations.
Key remapping is the other half. A mapped type can rename as it iterates using an as clause: { [K in keyof T as get${Capitalize<K & string>}]: () => T[K] } turns a data shape into a getter interface. Returning never from the as clause removes the key, which is how conditional filtering of properties is done — "all the string-valued keys" is a one-liner.
Parsing is where it gets genuinely useful. With infer inside a template pattern, the type system can pull structure out of a string: extracting :id and :slug from /users/:id/posts/:slug gives you typed route parameters derived from the route itself, with no duplication and no drift. The same technique types query-string keys, i18n message placeholders, and CSS-in-JS property names.
Two limits are worth respecting. Combinatorial explosion is real — a template over three unions of ten members each is a thousand-member union, and the compiler will slow down or refuse. And error messages on a failed template match are unhelpful, often listing an enormous union of candidates, so keep the patterns shallow.
The practical judgement: use these where a string convention already exists and the alternative is manual duplication. Do not invent a convention just to encode it in types.
Why it matters
This is the machinery behind the type safety in modern routing libraries, tRPC, and typed i18n — reading their types requires it, and diagnosing a failure requires it more.
For interviews it is a depth signal rather than a daily tool: being able to explain how a router infers { id: string } from a path string shows you understand the type system as a language.
Key points
- Template literal types build string types, and unions inside them produce the cross-product.
Uppercase,Lowercase,Capitalize, andUncapitalizecover the case conventions JavaScript relies on.- Key remapping with
asrenames keys during a mapped type; returningneverdeletes them. inferinside a template pattern parses structure out of a string — this is how typed route params work.- Combinatorial blowup is a real limit; keep unions small in template positions.
- Failed matches produce poor errors, so prefer shallow patterns and named helpers.
- Encode conventions that already exist; do not create one for the sake of the type trick.