Un template literal type costruisce tipi letterali stringa con la stessa sintassi a backtick di una template string JavaScript. `on${Capitalize<"click" | "focus">}` è il tipo "onClick" | "onFocus", calcolato dal compilatore:
I template literal types esistono solo in compilazione. Controllano i letterali stringa e i valori tipizzati mentre scrivi il codice; non aggiungono nulla all'output JavaScript. La tabella di handler qui sopra usa Record per richiedere una funzione per ogni nome.
Sintassi
Dentro i backtick scrivi testo letterale e segnaposto ${...}. Un segnaposto contiene un tipo, non un valore: un tipo letterale stringa, numero, bigint o boolean, una loro union, oppure uno dei tipi ampi string, number, bigint, boolean, null e undefined.
Un segnaposto con un tipo ampio come string o number crea un pattern: il tipo resta `hello ${string}` e qualsiasi stringa corrispondente viene accettata. Un segnaposto con una union finita, come boolean, viene espanso nei suoi membri.
Le union si moltiplicano
Con più union, il risultato è ogni combinazione:
Tre dimensioni per due toni danno sei membri. Il numero cresce in fretta: cinque segnaposto che contengono ciascuno una union di dieci lettere darebbero 100.000 membri, e TypeScript rifiuta con error TS2590: Expression produces a union type that is too complex to represent. Usa un segnaposto ampio come ${string} quando non ti serve ogni valore esatto.
Uppercase, Lowercase, Capitalize, Uncapitalize
Quattro tipi built-in cambiano maiuscole e minuscole dei tipi letterali stringa. Sono intrinseci: implementati dentro il compilatore, non scritti in TypeScript.
| Tipo | Input | Risultato |
|---|---|---|
Uppercase<S> | "hello world" | "HELLO WORLD" |
Lowercase<S> | "Content-Type" | "content-type" |
Capitalize<S> | "hello world" | "Hello world" |
Uncapitalize<S> | "UserName" | "userName" |
Cambiano solo i tipi. Per costruire la stringa corrispondente in esecuzione devi comunque chiamare toUpperCase() o tagliare e mettere la maiuscola da te, e dire a TypeScript che il risultato ha il tipo preciso:
Serve as perché toUpperCase() è tipizzato per restituire un semplice string. La firma della funzione è ciò che vedono i chiamanti, quindi capitalize("report") ha il tipo letterale "Report".
Pattern di stringa: ${number}px e simili
Un tipo pattern accetta ogni stringa di una certa forma. È comodo per valori CSS, id e chiavi con un prefisso noto:
${number} accetta qualsiasi stringa che JavaScript legge come numero, e questo è più permissivo di quanto sembri: "-3px", "1e3px" e "0x10px" superano tutti il controllo. Considera questi pattern una protezione contro i refusi nei letterali, non una validazione completa.
Template literal con i mapped type
I template literal types sono più utili come clausola as di un mapped type, dove generano nomi di proprietà a partire da altri nomi di proprietà:
string & K tiene solo le chiavi stringa, perché Capitalize non accetta numeri né symbol. Ogni callback prende il tipo del parametro dalla proprietà che osserva.
Parsing di stringhe con infer
In un conditional type, un template literal può fare il match di una stringa e catturarne delle parti con infer. Questo estrae i nomi dei parametri da un pattern di route:
Ometti postId nella chiamata e il compilatore lo segnala come mancante.
Le espressioni template si allargano a string
Un'espressione template string nel codice normale ha tipo string, anche quando ogni parte è un tipo letterale. Aggiungi as const per mantenere il template literal type:
Senza as const, assegnare loose a `log:${Level}` fallisce, perché string potrebbe essere qualsiasi cosa.
Domande frequenti
Cosa sono i template literal types in TypeScript?
Tipi letterali stringa scritti con backtick e segnaposto ${...}, come le template string di JavaScript ma a livello di tipi. type Greeting = `hello ${string}` accetta qualsiasi stringa che inizia con hello , e `on${Capitalize<"click">}` è il tipo letterale "onClick".
Cosa succede se metti una union in un template literal type?
Il template viene espanso per ogni membro, e con più union ottieni tutte le combinazioni. `${"sm" | "lg"}-${"red" | "blue"}` è "sm-red" | "sm-blue" | "lg-red" | "lg-blue". Le combinazioni molto grandi falliscono con l'errore TS2590.
Cosa fanno Uppercase, Lowercase, Capitalize e Uncapitalize?
Sono tipi built-in che trasformano i tipi letterali stringa: Uppercase<"id"> è "ID", Lowercase<"ID"> è "id", Capitalize<"name"> è "Name" e Uncapitalize<"Name"> è "name". Cambiano solo i tipi; per cambiare una stringa in esecuzione devi comunque chiamare toUpperCase() e simili.
I template literal types validano le stringhe in esecuzione?
No. Come tutti i tipi di TypeScript vengono cancellati, quindi controllano i letterali stringa e i valori tipizzati solo in compilazione. Una stringa che arriva in esecuzione, da un JSON o dall'input dell'utente, è solo string finché non la controlli con il tuo codice.
Perché la mia template string ha tipo string invece di un tipo letterale?
Un'espressione template come `on${event}` viene allargata a string quando la assegni a una variabile. Aggiungi as const (`on${event}` as const) o annota il tipo di destinazione, e TypeScript mantiene il template literal type, per esempio "onclick" | "onfocus".