Tipo mapeado que combina las variaciones del tipo dado.
Dado un tipo que contiene todas las posibilidades (por ejemplo, una unión no etiquetada):
type Input = {
a: string,
b: number,
c: boolean,
};
Quiero mapearlo con este tipo de API:
type MapItSomehow<t> = ???;
type Output = MapItSomehow<input>;
Y, en última instancia, obtener esto:
type Output = {
a: string,
b: undefined,
c: undefined,
} | {
a: undefined,
b: number,
c: undefined,
} | {
a: undefined,
b: undefined,
c: boolean,
};
La prueba de que esto funciona es si puedo hacer lo siguiente:
“`ts
let r: Result = ([] as Result[])[0];
if ('a' in r) {
r.a.trim() // no r.a!.trim()
}
else if // lo mismo para cada campo …
“`
davy.ai
Para lograr el mapeo deseado, podemos utilizar el operador
keyof
para generar un tipo unión con todas las claves en el tipo de entradaT
. Luego, podemos usar tipos mapeados y tipos condicionales para crear un nuevo tipo que incluya todas las combinaciones posibles de campos en el tipo de entrada, conundefined
como tipo para los campos excluidos. Aquí está el código:Veamos esto más detalladamente. El tipo
MapItSomehow
mapea todas las clavesK
en el tipo de entradaT
utilizando un tipo mapeado:Para cada clave
K
, este tipo crea un nuevo tipo objeto que incluye el campoK
con su tipo originalT[K]
, y todos los demás campos del tipo de entrada con el tipoundefined
. El tipo de utilidadExclude
se utiliza para crear una unión con todas las otras claves del tipo de entrada, y el operador?:
se utiliza para hacer que esos campos sean opcionales con el tipoundefined
.Finalmente, se utiliza el indexado
[keyof T]
para crear un tipo unión con todas las combinaciones posibles de campos en el tipo de entrada.Esto resulta en el tipo
Output
que estábamos tratando de lograr:Con esta definición de tipo, podemos utilizar el operador
in
para verificar si un campo está presente en un valor de tipoOutput
, y TypeScript correctamente estrechará el tipo del valor según la verificación.