Cuando no quieres repetirte, a veces un tipo necesita basarse en otro tipo.
Los tipos mapeados se basan en la sintaxis de las firmas de índice, que se utilizan para declarar los tipos de propiedades que no se han declarado con anticipación:
Prueba este código ↗
type OnlyBoolsAndHorses = {
[ key : string ] : boolean | Horse ;
const conforms : OnlyBoolsAndHorses = {
Un tipo mapeado es un tipo genérico que usa una unión de PropertyKey
s (creadas con frecuencia mediante un keyof
) para iterar a través de claves para crear un tipo:
Prueba este código ↗
type OptionsFlags< Type > = {
[ Property in keyof Type ] : boolean ;
En este ejemplo, OptionsFlags
tomará todas las propiedades del tipo Type
y cambiará sus valores para que sean booleanos.
Prueba este código ↗
newUserProfile : () => void ;
type FeatureOptions = OptionsFlags < Features >;
Modificadores de mapeo
Hay dos modificadores adicionales que se pueden aplicar durante el mapeo: readonly
y ?
que afectan la mutabilidad y la opcionalidad respectivamente.
Puedes eliminar o agregar estos modificadores anteponiendo -
o +
. Si no agregas un prefijo, se supone +
.
Prueba este código ↗
// Elimina los atributos de 'readonly' de las propiedades de un tipo
type CreateMutable< Type > = {
- readonly [ Property in keyof Type ] : Type [ Property ];
type UnlockedAccount = CreateMutable < LockedAccount >;
Prueba este código ↗
// Elimina atributos 'optional' de las propiedades de un tipo
[ Property in keyof Type ] -?: Type [ Property ];
type User = Concrete < MaybeUser >;
Remapeo de claves con as
En TypeScript 4.1 y posteriores, puedes remapear claves en tipos mapeados con una cláusula as
en un tipo mapeado:
type MappedTypeWithNewProperties< Type > = {
[ Properties in keyof Type as NewKeyType ] : Type [ Properties ]
Puedes aprovechar funciones como tipos literales de plantilla para crear nuevos nombres de propiedades a partir de las anteriores:
Prueba este código ↗
[ Property in keyof Type as ` get ${ Capitalize < string & Property > } ` ] : () => Type [ Property ]
type LazyPerson = Getters < Person >;
getLocation : () => string ;
Puedes filtrar claves generando never
mediante un tipo condicional:
Prueba este código ↗
// Elimina la propiedad 'kind'
type RemoveKindField< Type > = {
[ Property in keyof Type as Exclude < Property , " kind " >] : Type [ Property ]
type KindlessCircle = RemoveKindField < Circle >;
Puedes mapear uniones arbitrarias, no solo uniones de string | number | symbol
, sino uniones de cualquier tipo:
Prueba este código ↗
type EventConfig< Events extends { kind : string }> = {
[ E in Events as E [ " kind " ]] : ( event : E ) => void ;
type SquareEvent = { kind : " square " , x : number , y : number };
type CircleEvent = { kind : " circle " , radius : number };
type Config = EventConfig < SquareEvent | CircleEvent >
square : ( event : SquareEvent ) => void ;
circle : ( event : CircleEvent ) => void ;
Exploración adicional
Los tipos mapeados funcionan bien con otras características en esta sección de manipulación de tipos, por ejemplo aquí está un tipo mapeado usando un tipo condicional que devuelve true
o false
dependiendo de si un objeto tiene la propiedad pii
establecida en el literal true
:
Prueba este código ↗
type ExtractPII< Type > = {
[ Property in keyof Type ] : Type [ Property ] extends { pii : true } ? true : false ;
id : { format : " incrementing " };
name : { type : string ; pii : true };
type ObjectsNeedingGDPRDeletion = ExtractPII < DBFields >;
type ObjectsNeedingGDPRDeletion = {