Un template literal type construye tipos literales de string con la misma sintaxis de comillas invertidas que un template string de JavaScript. `on${Capitalize<"click" | "focus">}` es el tipo "onClick" | "onFocus", calculado por el compilador:
Los template literal types solo existen en compilación. Comprueban literales de string y valores tipados mientras escribes código; no añaden nada al JavaScript de salida. La tabla de handlers de arriba usa Record para exigir una función por nombre.
Sintaxis
Dentro de las comillas invertidas escribes texto literal y marcadores ${...}. Un marcador contiene un tipo, no un valor: un tipo literal string, number, bigint o boolean, una unión de ellos, o uno de los tipos amplios string, number, bigint, boolean, null y undefined.
Un marcador con un tipo amplio como string o number crea un patrón: el tipo se queda como `hello ${string}` y acepta cualquier string que encaje. Un marcador con una unión finita, como boolean, se expande en sus miembros.
Las uniones se multiplican
Con varias uniones, el resultado son todas las combinaciones:
Tres tamaños por dos tonos dan seis miembros. La cuenta crece rápido: cinco marcadores con una unión de diez letras cada uno serían 100.000 miembros, y TypeScript se niega con error TS2590: Expression produces a union type that is too complex to represent. Usa un marcador amplio como ${string} cuando no necesites todos los valores exactos.
Uppercase, Lowercase, Capitalize, Uncapitalize
Cuatro tipos integrados cambian las mayúsculas y minúsculas de los tipos literales de string. Son intrínsecos: están implementados dentro del compilador, no escritos en TypeScript.
| Tipo | Entrada | Resultado |
|---|---|---|
Uppercase<S> | "hello world" | "HELLO WORLD" |
Lowercase<S> | "Content-Type" | "content-type" |
Capitalize<S> | "hello world" | "Hello world" |
Uncapitalize<S> | "UserName" | "userName" |
Solo cambian tipos. Para construir el string equivalente en ejecución, sigues llamando a toUpperCase() o cortando y poniendo la mayúscula tú mismo, y le dices a TypeScript que el resultado tiene el tipo preciso:
El as hace falta porque toUpperCase() está tipado para devolver un string normal. La firma de la función es lo que ve quien la llama, así que capitalize("report") tiene el tipo literal "Report".
Patrones de string: ${number}px y compañía
Un tipo patrón acepta cualquier string con una forma dada. Es práctico para valores CSS, ids y claves con un prefijo conocido:
${number} acepta cualquier string que JavaScript lea como número, lo cual es más permisivo de lo que parece: "-3px", "1e3px" y "0x10px" pasan la comprobación. Usa estos patrones como protección frente a erratas en literales, no como validación completa.
Template literals con mapped types
Los template literal types son más útiles como cláusula as de un mapped type, donde generan nombres de propiedades a partir de otros nombres de propiedades:
string & K conserva solo las claves string, porque Capitalize no acepta números ni símbolos. Cada callback recibe el tipo de su parámetro de la propiedad que vigila.
Analizar strings con infer
En un conditional type, un template literal puede encajar con un string y capturar partes de él con infer. Esto extrae los nombres de los parámetros de un patrón de ruta:
Si omites postId en la llamada, el compilador avisa de que falta.
Las expresiones de plantilla se amplían a string
Una expresión de template string en código normal tiene tipo string, aunque todas sus partes sean tipos literales. Añade as const para conservar el template literal type:
Sin as const, asignar loose a `log:${Level}` falla, porque string podría ser cualquier cosa.
Preguntas frecuentes
¿Qué son los template literal types en TypeScript?
Tipos literales de string escritos con comillas invertidas y marcadores ${...}, como los template strings de JavaScript pero a nivel de tipos. type Greeting = `hello ${string}` acepta cualquier string que empiece por hello , y `on${Capitalize<"click">}` es el tipo literal "onClick".
¿Qué pasa si pones una unión en un template literal type?
La plantilla se expande para cada miembro, y con varias uniones obtienes todas las combinaciones. `${"sm" | "lg"}-${"red" | "blue"}` es "sm-red" | "sm-blue" | "lg-red" | "lg-blue". Las combinaciones muy grandes fallan con el error TS2590.
¿Qué hacen Uppercase, Lowercase, Capitalize y Uncapitalize?
Son tipos integrados que transforman tipos literales de string: Uppercase<"id"> es "ID", Lowercase<"ID"> es "id", Capitalize<"name"> es "Name" y Uncapitalize<"Name"> es "name". Solo cambian tipos; para cambiar un string en ejecución sigues llamando a toUpperCase() y compañía.
¿Los template literal types validan strings en tiempo de ejecución?
No. Como todos los tipos de TypeScript, se borran, así que solo comprueban literales de string y valores tipados en compilación. Un string que llega en ejecución, desde JSON o una entrada del usuario, es solo string hasta que lo compruebas con tu propio código.
¿Por qué mi template string tiene tipo string en lugar de un tipo literal?
Una expresión de plantilla como `on${event}` se amplía a string al asignarla a una variable. Añade as const (`on${event}` as const) o anota el tipo de destino, y TypeScript conserva el template literal type, por ejemplo "onclick" | "onfocus".