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.