A template literal type looks exactly like a JavaScript template string but operates on types: interpolating a union type inside the backticks produces a new union covering every combination. Introduced in TypeScript 4.1 (2020), this is the mechanism behind the key-remapping as clause in mapped types (covered earlier) and lets a type precisely describe string patterns like event names, CSS properties, or API route paths.
Interpolating a union produces every combination
The result is a new union covering every combination of the interpolated union's members — not a single string, but every valid EventName the pattern can produce.
type EventName = "click" | "scroll" | "resize";
type HandlerName = `on${Capitalize<EventName>}`;
// "onClick" | "onScroll" | "onResize"
function addHandler(name: HandlerName) { /* ... */ }
addHandler("onClick"); // fine
// addHandler("onclick"); // COMPILE ERROR: lowercase doesn't match the patternCombining with mapped types: real, practical use
This is exactly the pattern used earlier for the Getters<T> example — the two features (mapped types and template literal types) compose directly.
type CSSProperty = "color" | "background" | "border";
type CSSVariable = `--${CSSProperty}`;
// "--color" | "--background" | "--border"
const styles: Record<CSSVariable, string> = {
"--color": "blue",
"--background": "white",
"--border": "1px solid black",
};Built-in intrinsic string manipulation types
TypeScript ships four built-in type-level string transformations — Uppercase, Lowercase, Capitalize, Uncapitalize — that operate purely on string literal types at compile time, with no runtime equivalent needed since they're erased entirely.
type Loud = Uppercase<"hello">; // "HELLO"
type Quiet = Lowercase<"HELLO">; // "hello"
type Title = Capitalize<"hello">; // "Hello"
type Mini = Uncapitalize<"Hello">; // "hello"