Codectionary / Developer documentation / TypeScript

Mapped Types

A mapped type builds a new type by transforming every property of an existing type, using syntax similar to a for...in loop at the type level: { [K in keyof T]: NewType }. This is the mechanism behind built-in utility types like Partial<T> and Readonly<T>, and lets you write your own systematic property transformations.

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