Saltar al contenido
webtype.orgDoce conceptos · 4/12

Concepto 4 de 12

Tipos mapeados

Un tipo mapeado es un bucle sobre una unión de claves que construye un objeto. `Partial`, `Required`, `Readonly` y `Pick` son una línea de esto cada uno, y cuando la forma te resulte familiar podrás escribir cualquiera de memoria.

La forma

type MyPartial<T> = { [K in keyof T]?: T[K] }
//                     ^^^^^^^^^^^^^^  ^  ^^^^
//                     key set         |  value type
//                                     modifier

Léelo así: para cada `K` de este conjunto de claves, produce una propiedad llamada `K` cuyo tipo es esa expresión. El conjunto de claves es cualquier unión de `string`, `number` o `symbol` — normalmente `keyof T`, a veces un parámetro, ocasionalmente algo calculado.

Los modificadores suman y restan

type Optional<T> = { [K in keyof T]+?: T[K] }   // add ?
type Required<T> = { [K in keyof T]-?: T[K] }   // remove ?
type Frozen<T> = { readonly [K in keyof T]: T[K] }
type Thawed<T> = { -readonly [K in keyof T]: T[K] }

Mapear sobre un `keyof T` desnudo es *homomórfico*, lo que significa que los modificadores `?` y `readonly` existentes se copian automáticamente. Por eso un mapeo identidad no cambia nada, y por eso quitar un modificador exige un menos explícito.

Renombrar claves con `as`

type Getters<T> = {
  [K in keyof T as `get${Capitalize<K & string>}`]: () => T[K]
}

// A key renamed to never disappears — this is how you filter.
type OnlyStrings<T> = {
  [K in keyof T as T[K] extends string ? K : never]: T[K]
}

La cláusula `as` reescribe cada clave mientras corre el mapeo. Una clave reescrita a `never` no puede existir, así que la propiedad se elimina — y es la única forma de quitar una propiedad de un tipo objeto.

El error más común

// Intent: keep only the string-valued properties.
type OnlyStrings<T> = {
  [K in keyof T]: T[K] extends string ? T[K] : never
}
// Every key survives; the rejected ones just hold never.
// { name: string; age: never }

Filtrar del lado del valor no puede eliminar una clave, solo vaciarla. El filtrado ocurre en la cláusula de clave con `as ... : never`, y confundir ambos produce un tipo que parece filtrado y no impone nada.

Para recordar

`{ [K in Claves]: Valor }` es el bucle. Los modificadores se aplican a la propiedad, `as` reescribe la clave, y `never` como clave es cómo desaparecen las cosas.

Se practica en