Q15 of 38 · TypeScript
What are mapped types in TypeScript, and how do they work?
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 };