Menu

TypeScript Template Literal Types: Syntax und Beispiele

Template Literal Types bauen String-Literaltypen mit derselben Backtick-Syntax wie Template Strings in JavaScript: on${Capitalize<E>}. Die Syntax, wie sich Unions multiplizieren, Uppercase und Capitalize, Muster wie ${number}px, Getter mit Mapped Types und Strings mit infer zerlegen.

Diese Seite enthält ausführbare Editoren - bearbeiten, ausführen und Ausgabe sofort sehen.

Ein Template Literal Type baut String-Literaltypen mit derselben Backtick-Syntax wie ein Template String in JavaScript. `on${Capitalize<"click" | "focus">}` ist der Typ "onClick" | "onFocus", berechnet vom Compiler:

Template Literal Types existieren nur beim Kompilieren. Sie prüfen String-Literale und typisierte Werte, während du Code schreibst; zur JavaScript-Ausgabe tragen sie nichts bei. Die Handler-Tabelle oben nutzt Record, um eine Funktion pro Name zu verlangen.

Syntax

Zwischen die Backticks schreibst du literalen Text und Platzhalter ${...}. Ein Platzhalter enthält einen Typ, keinen Wert: einen Literaltyp für string, number, bigint oder boolean, eine Union davon oder einen der breiten Typen string, number, bigint, boolean, null und undefined.

Ein Platzhalter mit einem breiten Typ wie string oder number ergibt ein Muster: Der Typ bleibt `hello ${string}`, und jeder passende String wird akzeptiert. Ein Platzhalter mit einer endlichen Union wie boolean wird in ihre Mitglieder aufgelöst.

Unions multiplizieren sich

Bei mehreren Unions ist das Ergebnis jede Kombination:

Drei Größen mal zwei Farbtöne ergibt sechs Mitglieder. Die Anzahl wächst schnell: Fünf Platzhalter mit je einer Union aus zehn Buchstaben ergäben 100,000 Mitglieder, und TypeScript verweigert das mit error TS2590: Expression produces a union type that is too complex to represent. Nimm einen breiten Platzhalter wie ${string}, wenn du nicht jeden genauen Wert brauchst.

Uppercase, Lowercase, Capitalize, Uncapitalize

Vier eingebaute Typen ändern die Groß- und Kleinschreibung von String-Literaltypen. Sie sind intrinsisch: im Compiler implementiert, nicht in TypeScript geschrieben.

TypEingabeErgebnis
Uppercase<S>"hello world""HELLO WORLD"
Lowercase<S>"Content-Type""content-type"
Capitalize<S>"hello world""Hello world"
Uncapitalize<S>"UserName""userName"

Sie ändern nur Typen. Um den passenden String zur Laufzeit zu bauen, rufst du weiterhin toUpperCase() auf oder schneidest den String zurecht und schreibst ihn selbst groß, und sagst TypeScript, dass das Ergebnis den genauen Typ hat:

Das as ist nötig, weil toUpperCase() so typisiert ist, dass es einen einfachen string zurückgibt. Aufrufer sehen die Signatur der Funktion, also hat capitalize("report") den Literaltyp "Report".

String-Muster: ${number}px und Co.

Ein Mustertyp akzeptiert jeden String einer bestimmten Form. Das ist praktisch für CSS-Werte, IDs und Schlüssel mit bekanntem Präfix:

${number} akzeptiert jeden String, den JavaScript als Zahl liest, und das ist lockerer, als es aussieht: "-3px", "1e3px" und "0x10px" bestehen alle die Typprüfung. Betrachte diese Muster als Schutz vor Tippfehlern in Literalen, nicht als vollständige Validierung.

Template Literals mit Mapped Types

Am nützlichsten sind Template Literal Types als as-Klausel eines Mapped Types, wo sie Eigenschaftsnamen aus anderen Eigenschaftsnamen erzeugen:

string & K behält nur String-Schlüssel, weil Capitalize keine Zahlen oder Symbole akzeptiert. Jeder Callback bekommt seinen Parametertyp von der Eigenschaft, die er beobachtet.

Strings mit infer zerlegen

In einem Conditional Type kann ein Template Literal einen String abgleichen und Teile davon mit infer festhalten. So werden die Parameternamen aus einem Routenmuster herausgezogen:

Lässt du postId im Aufruf weg, meldet der Compiler es als fehlend.

Template-Ausdrücke werden zu string erweitert

Ein Template-String-Ausdruck in normalem Code ist als string typisiert, auch wenn jeder Teil ein Literaltyp ist. Ergänze as const, um den Template Literal Type zu behalten:

Ohne as const scheitert die Zuweisung von loose an `log:${Level}`, weil string alles sein könnte.

Häufig gestellte Fragen

Was sind Template Literal Types in TypeScript?

String-Literaltypen, geschrieben mit Backticks und Platzhaltern ${...}, wie Template Strings in JavaScript, aber auf Typebene. type Greeting = `hello ${string}` akzeptiert jeden String, der mit hello beginnt, und `on${Capitalize<"click">}` ist der Literaltyp "onClick".

Was passiert, wenn man eine Union in einen Template Literal Type setzt?

Das Template wird für jedes Mitglied ausgewertet, und bei mehreren Unions bekommst du jede Kombination. `${"sm" | "lg"}-${"red" | "blue"}` ist "sm-red" | "sm-blue" | "lg-red" | "lg-blue". Sehr große Kombinationen scheitern mit dem Fehler TS2590.

Was machen Uppercase, Lowercase, Capitalize und Uncapitalize?

Das sind eingebaute Typen, die String-Literaltypen umwandeln: Uppercase<"id"> ist "ID", Lowercase<"ID"> ist "id", Capitalize<"name"> ist "Name" und Uncapitalize<"Name"> ist "name". Sie ändern nur Typen; um einen String zur Laufzeit zu ändern, rufst du weiterhin toUpperCase() und Co. auf.

Validieren Template Literal Types Strings zur Laufzeit?

Nein. Wie jeder TypeScript-Typ werden sie entfernt, sie prüfen also nur String-Literale und typisierte Werte beim Kompilieren. Ein String, der zur Laufzeit ankommt, aus JSON oder einer Benutzereingabe, ist einfach string, bis du ihn mit eigenem Code prüfst.

Warum ist mein Template String als string typisiert statt als Literaltyp?

Ein Template-Ausdruck wie `on${event}` wird bei der Zuweisung an eine Variable zu string erweitert. Ergänze as const (`on${event}` as const) oder annotiere den Zieltyp, dann behält TypeScript den Template Literal Type, zum Beispiel "onclick" | "onfocus".

Coddy programming languages illustration

Lerne mit Coddy zu programmieren

LOS GEHT'S