Syncing account progress…

Back

Advanced · 18 min

Mapped types and modifiers

Transform every property in a type without repeating its keys.

Map a known set of keys

A mapped type iterates over a key union. Each property can receive a new value type or reuse its original indexed type. This describes an object shape; it does not create the object or loop at runtime.

type Flags<T> = { [K in keyof T]: boolean };
type Preferences = { email: string; reminders: number };
const enabled: Flags<Preferences> = { email: true, reminders: false };
console.log(enabled.email);

Output

true

Remove modifiers deliberately

The minus modifier removes readonly or optional status at the mapped level. The resulting type still needs an actual value containing every required field. This transformation is shallow and does not fill missing values.

type Editable<T> = { -readonly [K in keyof T]-?: T[K] };
type Draft = { readonly title?: string };
const draft: Editable<Draft> = { title: "First" };
draft.title = "Ready";
console.log(draft.title);

Output

Ready

Put it into practice

  1. Predict the output and explain which relationships the types enforce.
  2. Fix the task while preserving its type contract, then check both practice questions.

Try it yourself

Code runs on this device. When you are signed in, drafts sync to your account.

Complete preference flags

Add "reminders" with the value false. Keep the mapped type.

Show solution
type Flags<T> = { [K in keyof T]: boolean };
type Preferences = { email: string; reminders: number };
const enabled: Flags<Preferences> = { email: true, reminders: false };
console.log(enabled.email);

Both source keys appear in the mapped contract. Supplying the missing flag fixes the error without changing the source type.

Practice