Concepto 9 de 12
Tipos de literal de plantilla
Los tipos de literal de plantilla permiten al compilador construir y emparejar cadenas. Combinados con `infer` y recursión pueden analizar — así una ruta se convierte en un objeto de parámetros, y así se comprueban en compilación las claves i18n y los nombres de columna de un ORM.
Construir y convertir a cadena
type Greeting = `hello ${string}` type Event = `on${'Click' | 'Focus'}` // 'onClick' | 'onFocus' type AsText = `${42}` // '42' // Interpolating a union multiplies out every combination. type Cell = `${'a' | 'b'}${1 | 2}` // 'a1' | 'a2' | 'b1' | 'b2'
Interpolar una unión produce el producto cartesiano, que crece rápido — TypeScript limita el resultado a 100.000 miembros y da error por encima. Convertir un número con `` `${N}` `` es la forma estándar de transformar un problema aritmético en uno de texto.
El emparejamiento está anclado y es ávido por la izquierda
type StartsWith<S, P extends string> = S extends `${P}${string}` ? true : false type EndsWith<S, P extends string> = S extends `${string}${P}` ? true : false type Contains<S, P extends string> = S extends `${string}${P}${string}` ? true : false // Greedy from the left: Head binds the SHORTEST prefix that works. type Split1<S> = S extends `${infer Head}-${infer Tail}` ? [Head, Tail] : never type X = Split1<'a-b-c'> // ['a', 'b-c']
Un patrón debe emparejar toda la cadena, así que donde pongas `${string}` es donde permites holgura. Holgura delante significa «contiene», detrás «empieza por», y a ambos lados significa que has escrito sin querer un test de subcadena.
Los cuatro tipos intrínsecos de mayúsculas
Uppercase<'abc'> // 'ABC' Lowercase<'ABC'> // 'abc' Capitalize<'abc'> // 'Abc' Uncapitalize<'Abc'> // 'abc'
Estos cuatro están implementados de forma nativa en el compilador y no tienen código TypeScript. Recurre a ellos antes de escribir una recursión carácter a carácter — `CamelCase` y compañía son unas pocas líneas con ellos y una pesadilla sin ellos.
El error más común
type Replace<S extends string, From extends string, To extends string> = S extends `${infer H}${From}${infer T}` ? `${H}${To}${T}` : S Replace<'abc', '', 'x'> // 'xabc' — not 'abc'
La cadena vacía cabe entre dos caracteres cualesquiera, así que una aguja vacía encaja de inmediato con `H` vacío. Es el `null` de los tipos de literal de plantilla: encaja en todas partes y rompe en silencio los patrones que asumen que encajar significa haber encontrado algo.
Para recordar
Los patrones están anclados por ambos extremos y son ávidos por la izquierda. Dónde permites holgura decide qué estás preguntando de verdad, y la cadena vacía siempre es el caso límite.