Nutze Template-Literal-Typen, um Unions über kartesische Produkte zu erzeugen und String-Literale mit infer zu zerlegen.
Diese Lektion in Kodokon öffnenTemplate-Literal-Typen bringen die Syntax der Template-Literale in die Welt der Typen. Interpoliere eine Union, und der Compiler berechnet das kartesische Produkt: Jede mögliche Kombination wird zu einem Mitglied des Ergebnisses. Das ist das Werkzeug, mit dem du Event-Schlüssel, Routen oder Design-System-Tokens zeichengenau typisierst.
type Lang = "fr" | "en";
type Theme = "light" | "dark";
type ThemeKey = `${Lang}-${Theme}`;
// "fr-light" | "fr-dark" | "en-light" | "en-dark"Die wahre Stärke zeigt sich in Kombination mit infer: Ein Template-Literal-Typ wird zu einem Abgleichmuster für Zeichenketten. Der Compiler zerschneidet das Eingabeliteral, um jedes Segment zu treffen; wenn mehrere Aufteilungen möglich sind, gewinnt das erste Vorkommen des Trennzeichens. Ergänze Rekursion, und du erhältst echte Parser, die zur Compile-Zeit ausgewertet werden.
type Split<S extends string, Sep extends string> =
S extends `${infer Head}${Sep}${infer Rest}`
? [Head, ...Split<Rest, Sep>]
: [S];
type Parts = Split<"a.b.c", ".">;
// ["a", "b", "c"]Dieses Muster glänzt beim Extrahieren der Parameter einer Route im Express-Stil. Jeder rekursive Aufruf verbraucht ein :param-Segment, und die finale Union listet jeden Parameternamen auf, den du anschließend in ein Record geben kannst, um die Signatur des Handlers zu typisieren.
type Params<Path extends string> =
Path extends `${string}:${infer P}/${infer Rest}`
? P | Params<Rest>
: Path extends `${string}:${infer P}`
? P
: never;
type RouteParams = Params<"/users/:id/posts/:postId">;
// "id" | "postId"TypeScript liefert vier intrinsische Hilfstypen mit - Uppercase, Lowercase, Capitalize, Uncapitalize -, die direkt im Compiler implementiert sind (das Schlüsselwort intrinsic), du kannst sie also nicht selbst nachbauen. Ein weiteres Muster aus der Produktion: string & {}. In einer Union würde string die Literale verschlucken und der Editor würde die Autovervollständigung verlieren; die Intersection mit {} erzeugt einen gleichwertigen, aber eigenständigen Typ, den der Compiler nicht reduziert.
type Method = "get" | "post";
type Handler = `on${Capitalize<Method>}`;
// "onGet" | "onPost"
type KnownColor = "red" | "green" | "blue";
type Color = KnownColor | (string & {});
declare function paint(color: Color): void;
paint("red"); // suggested by autocompletion
paint("#ff8800"); // also acceptedA 3 Mitglieder hat und B 4, wie viele Mitglieder enthält dann ${A}-${B}?Capitalize, angewendet auf das Literal "hello world"?KnownColor | (string & {}) statt KnownColor | string?