Template-Literal-Typen ermöglichen es dir, neue String-Literal-Typen zu erstellen, indem du andere Typen in ein Template interpolierst — String-Manipulation auf der Typ-Ebene.
ts
type Greeting = `Hello, ${string}`;
const a: Greeting = "Hello, world"; // ✅
const b: Greeting = "Hi there"; // ❌ doesn't match the pattern
Kombination mit Unions — sie verteilen sich
ts
type Color = "red" | "blue";
type Shade = "light" | "dark";
type Variant = `${Shade}-${Color}`;
// "light-red" | "light-blue" | "dark-red" | "dark-blue" — all combinations
Der Compiler expandiert jede Kombination der Unions — nützlich, um automatisch gültige String-Schlüssel (CSS-Klassen, Event-Namen, Route-Muster) zu generieren.
Ein echtes Muster: typisierte Event-Namen
ts
type Entity = "user" | "post";
type Event = `${Entity}:${"created" | "deleted"}`;
// "user:created" | "user:deleted" | "post:created" | "post:deleted"
function on(event: Event, cb: () => void) {}
on("user:created", () => {}); // ✅
on("user:updated", () => {}); // ❌ not a valid event
Mit Key-Remapping und intrinsic helpers
ts
type Getters<T> = {
[K in keyof T & string as `get${Capitalize<K>}`]: () => T[K];
};
// { name: string } → { getName: () => string }
Uppercase, Lowercase, Capitalize, Uncapitalize sind eingebaute intrinsic helpers.
Warum es wichtig ist
Template-Literal-Typen machen String-basierte APIs typensicher: Route-Parameter, Event-Systeme, CSS-in-JS, ORM-Spaltennamen.
Anstatt jeden beliebigen string zu akzeptieren, kannst du auf eine präzise, generierte Menge gültiger Strings beschränken — Tippfehler zur Compile-Zeit an Stellen abfangen, die früher stringly-typed waren.
