Mapped Types
Builtin Mapped Types
Basic Mapped Types
type Readonly<T> = { readonly [P in keyof T]: T[P] }
type Partial<T> = { [P in keyof T]?: T[P] }
type ReadonlyPartial<T> = { readonly [P in keyof T]?: T[P] }
type Required<T> = { [P in keyof T]-?: T[P] }
type Nullable<T> = { [P in keyof T]: T[P] | null }
type NonNullable<T> = T extends null | undefined ? never : T
type Clone<T> = { [P in keyof T]: T[P] }
type Stringify<T> = { [P in keyof T]: string }
Union Mapped Types
With distributive conditional type:
type Extract<T, U> = T extends U ? T : never
type Exclude<T, U> = T extends U ? never : T
Key Mapped Types
type Pick<T, K extends keyof T> = { [P in K]: T[P] }
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>
type Record<K extends keyof any, T> = { [P in K]: T }
Function Mapped Types
type Parameters<T extends (...args: any) => any> = T extends (
...args: infer P
) => any
? P
: never
type ConstructorParameters<T extends new (...args: any) => any>
= T extends new (...args: infer P) => any ? P : never
type ReturnType<T extends (...args: any) => any> = T extends (
...args: any[]
) => infer R
? R
: any
type InstanceType<T extends new (...args: any) => any> = T extends new (
...args: any
) => infer R
? R
: any
type ThisParameterType<T> = T extends (this: infer U, ...args: any[]) => any
? U
: unknown
Custom Mapped Types
Combine with:
in keyof.readonly.?.-.as.- Template literal types.
- Conditional types.
- Builtin types.
- Other mapped types.
- Other custom types.
// Removes 'readonly' attributes from a type's properties
type Mutable<T> = {
-readonly [K in keyof T]: T[K]
}
type DeepImmutable<T> = {
readonly [K in keyof T]: keyof T[K] extends undefined ? T[K] : Immutable<T[K]>
}
interface LockedAccount {
readonly id: string
readonly name: string
}
type UnlockedAccount = Mutable<LockedAccount>
// type UnlockedAccount = {
// id: string;
// name: string;
// };
// Mapped types via `as` type
type Getters<Type> = {
[Property in keyof Type as `get${Capitalize<
string & Property
>}`]: () => Type[Property]
}
interface Person {
name: string
age: number
location: string
}
type LazyPerson = Getters<Person>
// type LazyPerson = {
// getName: () => string;
// getAge: () => number;
// getLocation: () => string;
// }
// Remove the 'kind' property
type RemoveKindField<Type> = {
[Property in keyof Type as Exclude<Property, 'kind'>]: Type[Property]
}
interface Circle {
kind: 'circle'
radius: number
}
type KindlessCircle = RemoveKindField<Circle>
// type KindlessCircle = {
// radius: number;
// }
// Mapped type via conditional type
type ExtractPII<Type> = {
[Property in keyof Type]: Type[Property] extends { pii: true } ? true : false
}
interface DBFields {
id: { format: 'incrementing' }
name: { type: string, pii: true }
}
type ObjectsNeedingGDPRDeletion = ExtractPII<DBFields>
// type ObjectsNeedingGDPRDeletion = {
// id: false;
// name: true;
// }