Syntax
{ [K in keyof T]: NewValueType }Examples
A Custom Mapped Type
Building a type that makes every property optional - a simplified Partial<T>.
type MyPartial<T> = {
[K in keyof T]?: T[K];
};
interface User {
id: number;
name: string;
}
type PartialUser = MyPartial<User>;
// Equivalent to: { id?: number; name?: string }Mapped Type Modifiers
Adding or removing readonly and optional (?) modifiers, and transforming value types.
type ReadonlyVersion<T> = {
readonly [K in keyof T]: T[K];
};
type RemoveReadonly<T> = {
-readonly [K in keyof T]: T[K]; // the "-" removes the modifier instead of adding it
};
type Stringify<T> = {
[K in keyof T]: string; // transforms every property's VALUE type to string
};
interface Product { id: number; inStock: boolean; }
type StringProduct = Stringify<Product>; // { id: string; inStock: string }Best practices
- Use mapped types to systematically transform every property of an existing type, rather than manually retyping each property by hand
- Study TypeScript's built-in Partial, Required, and Readonly utility types - they are all implemented as short, readable mapped types
- Use the -readonly and -? modifier syntax when you specifically need to strip a modifier rather than add one
- Combine mapped types with conditional types (as clauses, key remapping) for advanced transformations, but keep an eye on readability as complexity grows
At a glance
- Purpose
- Static types for JavaScript
- File extension
- .ts ยท .tsx
- Runs in
- Compiled to JavaScript
- Usually used with
- JavaScript and its ecosystem
Specifications & further reading
Related TypeScript documentation
Generics Basics
Generics let you write reusable functions, classes, and types that work with a variety of types while still preserving type safety - rather than using any and losing that safety, or writing near-duplicate code for each type. A generic type parameter, conventionally named T, acts as a placeholder that gets filled in with a real type each time it is used.Generic Constraints
By default, a generic type parameter can be anything. The extends keyword constrains it to only types compatible with a given shape, letting you safely access specific properties or methods within the generic function while still supporting many different concrete types.Generic Classes and Interfaces
Classes and interfaces can also be generic, letting you build reusable data structures (like a Stack, Queue, or API response wrapper) that work with any type while remaining fully type-safe for whichever specific type is used in each instance.Conditional Types
A conditional type selects between two types based on a condition, using syntax that mirrors JavaScript's ternary operator: T extends U ? X : Y. This lets you build types that adapt based on the shape of another type, forming the foundation for many of TypeScript's built-in utility types.
Generics let you write reusable functions, classes, and types that work with a variety of types while still preserving type safety - rather than using any and losing that safety, or writing near-duplicate code for each type. A generic type parameter, conventionally named T, acts as a placeholder that gets filled in with a real type each time it is used.Generic Constraints
By default, a generic type parameter can be anything. The extends keyword constrains it to only types compatible with a given shape, letting you safely access specific properties or methods within the generic function while still supporting many different concrete types.Generic Classes and Interfaces
Classes and interfaces can also be generic, letting you build reusable data structures (like a Stack, Queue, or API response wrapper) that work with any type while remaining fully type-safe for whichever specific type is used in each instance.Conditional Types
A conditional type selects between two types based on a condition, using syntax that mirrors JavaScript's ternary operator: T extends U ? X : Y. This lets you build types that adapt based on the shape of another type, forming the foundation for many of TypeScript's built-in utility types.