Mapped Types
Mapped types iterate over the keys of a type to create a new type by transforming each property, enabling systematic type transformations.
Definition
type Mapped<T> = {
[K in keyof T]: NewType<T[K]>;
};Examples
type Nullable<T> = {
[K in keyof T]: T[K] | null;
};
interface User {
name: string;
age: number;
active: boolean;
}
type NullableUser = Nullable<User>;
// { name: string | null; age: number | null; active: boolean | null }type Getters<T> = {
[K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
};
interface Person {
name: string;
age: number;
}
type PersonGetters = Getters<Person>;
// { getName: () => string; getAge: () => number }type OnlyStrings<T> = {
[K in keyof T as T[K] extends string ? K : never]: T[K];
};
interface Mixed {
name: string;
age: number;
email: string;
active: boolean;
}
type StringProps = OnlyStrings<Mixed>;
// { name: string; email: string }Common Use Cases
- 1Creating readonly, optional, or nullable variants of types
- 2Generating getter/setter interfaces from data types
- 3Filtering object keys by value type
- 4Renaming keys with template literal types
- 5Building type-safe ORM query builders
Understanding Mapped Types
Mapped types are a foundational feature of TypeScript's type system that allow you to create new types by transforming each property of an existing type. The syntax [K in keyof T] iterates over every key of T, and you can modify the key, the value type, or add/remove modifiers for each property.
The built-in utility types Partial, Required, Readonly, and Record are all implemented as mapped types. Understanding mapped types means understanding the building blocks that these utility types are made of, and the ability to create your own custom transformations.
Mapped types support modifier manipulation with + and -. Adding +readonly makes properties readonly, while -? removes the optional modifier (making properties required). This modifier syntax is what powers the Required utility type.
TypeScript 4.1 introduced key remapping with the as clause, dramatically expanding what mapped types can express. With as, you can rename keys using template literal types, filter keys by removing them (mapping to never), or create entirely new key sets from existing types. This is the mechanism behind patterns like generating getter/setter methods from property names.
Filtering with as is particularly powerful. By writing [K in keyof T as T[K] extends string ? K : never], you create a new type containing only the string-valued properties of T. The never type in key position removes the property entirely.
Mapped types can also iterate over arbitrary unions, not just keyof T. You can write [K in "a" | "b" | "c"] to create an object with exactly those three keys. Combined with template literal types and conditional types, mapped types form a Turing-complete meta-programming system within TypeScript's type language.
Related Types
keyof TThe keyof type operator produces a union of all known public property keys of a type, enabling type-safe property access patterns.
Record<K, T>Constructs an object type whose property keys are K and whose property values are T, useful for dictionaries and lookup maps.
Partial<T>Constructs a type with all properties of T set to optional, allowing you to provide only a subset of the properties.
Readonly<T>Constructs a type with all properties of T set to readonly, preventing reassignment of properties after creation.
Template Literal TypesTemplate literal types combine string literal types with embedded expressions to create powerful string pattern types.
More Advanced Patterns
Explore TypeScript Types
Browse our complete reference of 30 TypeScript utility types with definitions, examples, and explanations.