Mapped types build on the syntax for index signatures, which are used to declare the types of properties which has not been declared ahead of time:
A mapped type is a generic type which uses a union created to iterate through the keys of one type to create another:
typeOptionsFlags <Type > = {[Property in keyofType ]: boolean;};
typeFeatureFlags = {darkMode : () => void;newUserProfile : () => void;};
type// ^ = type FeatureOptions = {FeatureOptions =OptionsFlags <FeatureFlags >;// darkMode: boolean;
// }
There are two additional modifiers which can be applied during mapping: readonly
and ?
which affect mutability and optionality respectively.
You can remove or add these modifiers by prefixing with or +
. If you don’t add a prefix, then +
is assumed.
// Removes 'optional' attributes from a type's propertiestypeConcrete <Type > = {[Property in keyofType ]-?:Type [Property ];};
typeMaybeUser = {id : string;name ?: string;age ?: number;};
type// ^ = type User = {User =Concrete <MaybeUser >;// id: string;
// name: string;
// age: number;
Key Remapping via as
ts
You can leverage features like to create new property names from prior ones:
You can filter out keys by producing never
via a conditional type:
// Remove the 'kind' propertytypeRemoveKindField <T > = {[K in keyofT asExclude <K , "kind">]:T [K ]};
interfaceCircle {kind : "circle";radius : number;}
type// ^ = type KindlessCircle = {KindlessCircle =RemoveKindField <Circle >;// radius: number;
// }
Further Exploration
ts
type ExtractPII<Type> = {[Property in keyof Type]: Type[Property] extends { pii: true } ? true : false;};type DBFields = {id: { format: "incrementing" };name: { type: string; pii: true };};type ObjectsNeedingGDPRDeletion = CreateMutable<DBFields>;