Suggest an editImprove this articleRefine the answer for “What is a "mapped type"?”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)A **mapped type** is a **type created from another type (or a set of keys)** by **iterating over its keys** and **modifying** properties (their types, names, modifiers). **Key point:** you could call it "the type-level equivalent of a `for...in` loop over an object's keys".Shown above the full answer for quick recall.Answer (EN)Image## What a Mapped Type Is A **mapped type** is a **type created from another type (or a set of keys)** by **iterating over its keys** and **modifying** properties (their types, names, modifiers). You could say it is "the type-level equivalent of a `for...in` loop over an object's keys". --- ### Syntax ```javascript type NewType = { [K in Keys]: Type; } ``` - `K` is a variable representing a key; - `in` is an operator that iterates over the values of the union `Keys`; - `Type` is the value type we assign to every key. --- ## Example 1. A simple mapping ```javascript type User = { name: string; age: number; }; type Nullable<T> = { [K in keyof T]: T[K] | null; }; // Transformed type: type NullableUser = Nullable<User>; /* { name: string | null; age: number | null; } */ ``` Here: - `keyof T` is `"name" | "age"`; - `[K in keyof T]` iterates over `"name"` and `"age"`; - every field is assigned `T[K] | null`. --- ## Example 2. Using modifiers In mapped types you can **change the modifiers** of properties: | Modifier | What it does | |---|---| | `?` | makes the property **optional** | | `-?` | makes the property **required** | | `readonly` | makes the property **read-only** | | `-readonly` | removes `readonly` | --- ### Example ```javascript type Optional<T> = { [K in keyof T]?: T[K]; }; type ReadonlyCopy<T> = { readonly [K in keyof T]: T[K]; }; type Mutable<T> = { -readonly [K in keyof T]: T[K]; }; type RequiredCopy<T> = { [K in keyof T]-?: T[K]; }; ``` --- ## Example 3. Implementing the standard utilities This is how many of the built-in utility types are constructed: ```javascript // Partial<T> type Partial<T> = { [K in keyof T]?: T[K]; }; // Required<T> type Required<T> = { [K in keyof T]-?: T[K]; }; // Readonly<T> type Readonly<T> = { readonly [K in keyof T]: T[K]; }; // Pick<T, K> type Pick<T, K extends keyof T> = { [P in K]: T[P]; }; // Record<K, T> type Record<K extends string | number | symbol, T> = { [P in K]: T; }; ``` --- ## Example 4. Transforming keys You can **rename properties** using the `as` construct (TypeScript >= 4.1): ```javascript type UppercaseKeys<T> = { [K in keyof T as Uppercase<string & K>]: T[K]; }; type User = { name: string; age: number; }; type UpperUser = UppercaseKeys<User>; /* { NAME: string; AGE: number; } */ ``` > Here `as Uppercase<...>` renames the keys to uppercase. --- ## Example 5. Filtering keys You can even **remove** keys from a type using `never`: ```javascript type RemoveNever<T> = { [K in keyof T as T[K] extends never ? never : K]: T[K]; }; type Example = { a: string; b: never; c: number; }; type Clean = RemoveNever<Example>; // { a: string; c: number } ``` --- ## Example 6. Combining with conditional types Mapped types are often **combined** with conditional types for flexible transformations: ```javascript type MakeOptionalIfNullable<T> = { [K in keyof T as null extends T[K] ? K : never]?: T[K]; }; type User = { id: number; name: string | null; age: number; }; type OptionalNullable = MakeOptionalIfNullable<User>; // { name?: string | null } ``` --- ## Example 7. Dynamically building API types ```javascript type Events = "click" | "submit" | "hover"; type EventHandlers = { [E in Events as `on${Capitalize<E>}`]: (event: E) => void; }; /* { onClick: (event: "click") => void; onSubmit: (event: "submit") => void; onHover: (event: "hover") => void; } */ ``` --- ## How TypeScript thinks about it TypeScript essentially does the following: ```javascript // pseudocode let result = {}; for (let key of Keys) { result[key] = Type; } return result; ``` --- ## Advantages of mapped types They let you **automatically derive types** They eliminate code duplication (you do not have to rewrite fields by hand) They work great with `keyof`, `Conditional Types`, `Template Literals` They are the basis of all built-in utility types --- ## Summary | Concept | Description | |---|---| | **Mapped type** | A type created by iterating over the keys of another type | | **Syntax** | `[K in Keys]: Type` | | **Extra capabilities** | `readonly`, `?`, `as`, `never` | | **Based on** | `keyof`, `in`, `conditional types` | | **Examples in TS** | `Partial`, `Required`, `Readonly`, `Pick`, `Record` |For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.