Concepto 6 de 12
Tipos condicionales
Un tipo condicional es el if a nivel de tipos. La pregunta que plantea es siempre la misma: ¿es el lado izquierdo asignable al derecho? No «¿son iguales?», no «¿es una instancia de?» — asignable, y en un solo sentido.
- Expresión
IsText<"hello"> - Se resuelve a
true - Expresión
IsText<42> - Se resuelve a
false
extends comprueba la asignabilidad. Un literal de cadena toma la rama true; un número, la rama false.
Definición del tipo
type IsText<T> = T extends string ? true : falseAsignabilidad, no igualdad
type A = 'hello' extends string ? true : false // true type B = string extends 'hello' ? true : false // false type C = never extends string ? true : false // true — never fits anywhere type D = { a: 1; b: 2 } extends { a: 1 } ? true : false // true
Un tipo más estrecho es asignable a uno más amplio, así que la prueba tiene dirección. Un objeto con propiedades de más es asignable a otro con menos, y por eso extends no sirve para comprobar que dos tipos objeto tengan la misma forma.
Cuando de verdad necesitas «el mismo tipo», necesitas el helper Equal sobre el que se apoya cada comprobación de este sitio — dos condicionales diferidos comparados por identidad, más estricto que la asignabilidad en ambos sentidos.
Las ramas se prueban en orden
type Describe<T> = T extends (...args: never[]) => unknown ? 'function' : T extends unknown[] ? 'array' : T extends object ? 'object' : 'primitive'
Los casos más estrechos deben ir primero. Funciones y arrays son ambos objetos, así que probar extends object pronto se los tragaría — la causa clásica de un DeepReadonly que destruye en silencio cada función que toca.
El error más común
// Intent: is T exactly string? type IsString<T> = T extends string ? true : false IsString<'hello'> // true — but 'hello' is not string, it is narrower IsString<any> // boolean — any matches both branches at once
extends responde a «cabe en», así que todo literal de cadena pasa una prueba de string. Y any es asignable a todo, así que un condicional con any devuelve la unión de ambas ramas — un resultado que casi nunca es el que se pretendía.
Ejercicio
Responde true cuando T sea string, y false en caso contrario.
Pruébalo
2IsString<'a'>—→ trueIsString<number>—→ false
Para recordar
Los condicionales preguntan por asignabilidad y prueban las ramas en orden. Lo estrecho primero, y recurre a Equal en cuanto necesites igualdad real.

