Chapter 28: TypeScript Mapped Types

Mapped Types in TypeScript like we’re sitting together at a table in Hyderabad, whiteboard in front of us, typing slowly in the playground, and really understanding what happens under the hood.

Mapped types are one of the most powerful tools for creating new types by transforming (or copying with changes) the properties of an existing type. They let you iterate over keys of a type and decide what happens to each property — make them optional, readonly, change their value type, rename keys, filter some out, add prefixes, turn them into functions, etc.

They appeared early (TS 2.1) but became much more expressive with the as clause in TS 4.1 — that’s when they really exploded in popularity.

1. The absolute basic syntax (the loop over keys)

TypeScript
  • keyof Type → gives you a union of all property names (as string/number/symbol literals)
  • Property in … → like a for-of loop over that union
  • The result is a new object type where each key from the original gets a new value type (boolean here)
TypeScript

This is exactly how the built-in Partial<T>, Required<T>, Readonly<T> are implemented.

2. The most common built-in mapped types (you use them every day)

Utility What it does Internal mapped type equivalent (simplified)
Partial<T> All properties optional { [P in keyof T]?: T[P] }
Required<T> All properties required { [P in keyof T]-?: T[P] }
Readonly<T> All properties readonly { readonly [P in keyof T]: T[P] }
Pick<T,K> Keep only some keys { [P in K]: T[P] }
Omit<T,K> Remove some keys { [P in keyof T as P extends K ? never : P]: T[P] } (with as)
Record<K,T> Create object with specific keys → same type { [P in K]: T }

3. Modifiers: +? -? +readonly -readonly

These are very important — they add / remove optional / readonly flags.

TypeScript

4. Key remapping with as clause (TS 4.1+) — the game changer

This is where mapped types become really creative.

You can change the key name during the mapping.

TypeScript

Very common real patterns using as in 2026

A. Prefix / suffix keys

TypeScript

B. Filter out keys (return never to exclude)

TypeScript

C. Event handler map from union

TypeScript

D. String literal transformation (with template literals)

TypeScript

5. Mapped types + generics + conditionals (very powerful combo)

TypeScript

6. Quick cheat-sheet table (keep this handy)

Goal Syntax pattern Example output keys / notes
Make all optional [P in keyof T]?: T[P] Partial<T>
Make all required [P in keyof T]-?: T[P] Required<T>
Make all readonly readonly [P in keyof T]: T[P] Readonly<T>
Remove readonly -readonly [P in keyof T]: T[P] Mutable version
Rename / prefix keys [K in keyof T as prefix_${K}]: T[K] Needs string & K sometimes
Filter keys (exclude some) [K in keyof T as K extends “bad” ? never : K] Omit-like behavior
Keep only string values [K in keyof T as T[K] extends string ? K : never] Very useful for form fields, keys, etc.
Turn properties into functions [K in keyof T as on${Capitalize<K>}]: (v: T[K]) => void Event emitters, setters

7. Mini homework — try these in the playground today

  1. Create your own Mutable<T> that removes all readonly
  2. Make Prefixed<T, Prefix extends string> that adds a prefix to every key
  3. Create StringPropsOnly<T> that keeps only properties whose value is string
  4. Build HandlersFromEvents<T> where T is a union of event objects with kind: string literal

Which pattern looks most useful for your current code?

Want to go deeper into:

  • Combining mapped types with recursive conditionals
  • Real form / validation / API payload transformations
  • How libraries like Zod / tRPC use mapped types internally
  • Common performance / instantiation depth issues

Just say — we’ll zoom right into that next! 😄

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *