Q15 of 38 · TypeScript

What are mapped types in TypeScript, and how do they work?

TypeScriptMidtypescriptmapped-typeskeyofgenericsutility-types

Short answer

Short answer: Mapped types iterate over the keys of a type and transform each property. The syntax `{ [K in keyof T]: NewType }` produces a new type with the same keys but transformed values. They are how built-in utility types like `Partial`, `Readonly`, `Record`, and `Required` are implemented.

Detail

A mapped type creates a new type by transforming the properties of an existing type, using an iteration over a union of keys.

Basic syntax: { [K in Keys]: ValueType }. The K variable iterates over Keys (usually keyof T). The property type can reference T[K] for the original value type.

Modifiers: You can add or remove readonly and ? modifiers using + or - prefixes:

  • { readonly [K in keyof T]: T[K] } — adds readonly to all properties
  • { -readonly [K in keyof T]: T[K] } — removes readonly
  • { [K in keyof T]+?: T[K] } — makes all optional (Partial)
  • { [K in keyof T]-?: T[K] } — makes all required (Required)

Key remapping (TypeScript 4.1): as clause in mapped types lets you rename keys: { [K in keyof T as get${Capitalize<string & K>}]: () => T[K] } produces getter methods.

In test automation: Mapped types are used to create typed test data factories, builder patterns, and response shape validators without repeating type definitions.

// EXAMPLE

interface User { id: number; name: string; email: string; }

// Mapped type — replicate Partial manually
type MyPartial<T> = { [K in keyof T]?: T[K] };
type PartialUser = MyPartial<User>;
// { id?: number; name?: string; email?: string; }

// Mapped type — make all values a validator function
type Validators<T> = { [K in keyof T]: (val: unknown) => val is T[K] };

// Key remapping — create getter interface
type Getters<T> = {
  [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
};
// Getters<User> = { getId: () => number; getName: () => string; ... }

// Test: typed mock response builder
type MockBuilder<T> = {
  [K in keyof T]: (value: T[K]) => MockBuilder<T>;
} & { build: () => T };

// WHAT INTERVIEWERS LOOK FOR

The `[K in keyof T]` iteration syntax and modifier operators. Knowing the built-in utilities are implemented via mapped types. Key remapping with `as`. Senior candidates apply this to custom builder patterns or mock factories.

// COMMON PITFALL

Confusing mapped types with index signatures (`{ [key: string]: T }`) — index signatures allow any string key; mapped types iterate over a known union. They look similar but have very different semantics.