Mapped Types Flashcards
Q: What are Mapped Types in TypeScript and what is their basic syntax?
A: Mapped Types allow you to create new types based on old ones by transforming each property using a common pattern. They use index signature syntax with in operator.
// Basic syntax: [Property in keyof Type] type OptionsFlags<Type> = { [Property in keyof Type]: boolean; }; // Example usage: interface Features { darkMode: () => void; newUserProfile: () => void; } type FeatureOptions = OptionsFlags<Features>; // Result: // { // darkMode: boolean; // newUserProfile: boolean; // }
Q: How do you use mapping modifiers to change property modifiers in mapped types?
A: You can add or remove readonly and optional (?) modifiers using + or - prefix. If no prefix is specified, + is assumed.
// Remove readonly type CreateMutable<Type> = { -readonly [Property in keyof Type]: Type[Property]; }; // Remove optional type Concrete<Type> = { [Property in keyof Type]-?: Type[Property]; }; // Example: type MaybeUser = { id: string; name?: string; age?: number; }; type User = Concrete<MaybeUser>; // Result: all properties required // { // id: string; // name: string; // age: number; // }
Q: How do you remap keys in mapped types using the ‘as’ clause?
A: The as clause allows you to transform property names in mapped types, often used with template literal types or to filter out properties.
// Transform property names type Getters<Type> = { [Prop in keyof Type as `get${Capitalize<string & Prop>}`]: () => Type[Prop] }; interface Person { name: string; age: number; } type LazyPerson = Getters<Person>; // Result: // { // getName: () => string; // getAge: () => number; // } // Filter out properties type RemoveKindField<Type> = { [Prop in keyof Type as Exclude<Prop, "kind">]: Type[Prop] };
Q: How can you combine conditional types with mapped types?
A: You can use conditional types within mapped types to create more complex transformations based on property values.
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 = ExtractPII<DBFields>; // Result: // { // id: false; // name: true; // }