Conditional Types
Los tipos condicionales proporcionan una forma de hacer
lógica simple en el sistema de tipos de TypeScript. Esta
es definitivamente una característica avanzada, y es
bastante factible que no necesites usar esto en tu código
del día a día.
Un tipo condicional se parece a:
A extends B ? C : D
Donde la condición es si un tipo extiende una expresión
y, en caso afirmativo, qué tipo debe devolverse.
Veamos algunos ejemplos, para ser breves vamos a usar
letras simples para los genéricos. Esto es opcional, pero
al restringirnos a 60 caracteres es difícil que quepa en
la pantalla.
// Podemos crear un tipo condicional que permita extraer
tipos que sólo se ajusten a un animal que ladra.
type Cat = { meows: true };
type Dog = { barks: true };
type Cheetah = { meows: true; fast: true };
type Wolf = { barks: true; howls: true };
// Un lobo puede ladrar, por lo que retorna la forma del
objeto `Wolf`
type ExtractDogish = A extends { barks: true } ? A : never;
// Entonces podemos crear tipos soportados por ExtractDogish:
// Un gato no ladra, por lo que retorna `never`
type NeverCat = ExtractDogish
// Esto resulta útil cuando se quiere trabajar con un unión
de muchos tipos y reducir el número de opciones
potenciales en una unión:
type Wolfish = ExtractDogish
// Cuando aplicas ExtractDogish a una unión de tipos, es
igual a ejecutar los condicionales en cada uno de los
miembros del tipo:
type Animals = Cat | Dog | Cheetah | Wolf;
// = ExtractDogish
type Dogish = ExtractDogish
// Entonces, dependiendo de cuánto sepa el sistema de tipos
sobre el booleano, obtendrá diferentes tipos de retorno:
declare function getID
// En este caso, TypeScript puede saber el valor de retorno
al instante. Sin embargo, puede usar tipos condicionales
en funciones donde el tipo no se conoce todavía. Esto se
denomina tipo condicional diferido.
Igual que nuestro "Dogish" anterior, pero como función
let stringReturnValue = getID(true);
let numberReturnValue = getID(false);
let stringOrNumber = getID(Math.random() < 0.5);
// Hay una herramienta extra útil dentro de los tipos
condicionales, que es capaz de decirle específicamente a
TypeScript que debe inferir el tipo al diferir. Esa es la
palabra clave "infer".
"infer" se usa típicamente para crear meta-tipos que
inspeccionan los tipos existentes en tu código, piensa en
ello como crear una nueva variable dentro del tipo.
declare function isCatish
// Básicamente:
- Este es un tipo genérico condicional llamado
GetReturnValue el cual acepta un tipo como su primer
parámetro.
- El condicional revisa si el tipo es una función, y si
es así crea un nuevo tipo llamado R basado en el valor
retornado por esa función.
- Si la revisión pasa, el valor del tipo es el valor de
retorno inferido, sino es el tipo original.
type GetReturnValue
// Esto falla en la comprobación de ser una función, y sólo
devolvería el tipo pasado a ella.
type getIDReturn = GetReturnValue
type getCat = GetReturnValue