🔁 TypeScript – Mapped Types: A Complete Guide with Real-World Examples
🧲 Introduction – What Are Mapped Types in TypeScript?
In TypeScript, Mapped Types are a powerful and expressive feature that let you create new types by transforming properties from existing ones. With mapped types, you can add, remove, or change the modifiers (readonly
, optional
, etc.) of object properties in a reusable, scalable way.
🎯 In this guide, you’ll learn:
- What mapped types are and how they work
- Syntax and real-world applications
- How to combine them with utility types and conditional types
- Practical examples for UI state, forms, APIs, and more
📘 What Are Mapped Types?
Mapped types allow you to iterate over the keys of a type and apply transformations to each property using keyof
and in
.
📌 Basic Syntax:
type NewType = {
[Key in keyof OriginalType]: Transformation;
};
keyof OriginalType
gets all property keys.Key in ...
loops through each key.Transformation
is applied to each property’s type.
🧪 Example 1: Basic Mapped Type
type User = {
name: string;
age: number;
};
type StringifiedUser = {
[K in keyof User]: string;
};
🔍 Explanation:
- We loop through keys
"name"
and"age"
. - We assign
string
as the new type for all keys.
✅ Result:
// Equivalent to:
type StringifiedUser = {
name: string;
age: string;
};
🔐 Example 2: Making All Properties Optional
type Optional<T> = {
[K in keyof T]?: T[K];
};
type Post = {
title: string;
body: string;
};
type DraftPost = Optional<Post>;
🔍 Explanation:
?
makes each property optional.- Result:
{ title?: string; body?: string; }
✅ This is how TypeScript’s built-in Partial<T>
utility type works.
🔒 Example 3: Making All Properties Readonly
type ReadonlyProps<T> = {
readonly [K in keyof T]: T[K];
};
type Settings = {
theme: string;
notifications: boolean;
};
type FrozenSettings = ReadonlyProps<Settings>;
🔍 Explanation:
readonly
prevents future changes to values.- Now,
FrozenSettings
properties cannot be reassigned.
🔄 Example 4: Removing Optional or Readonly Modifiers
You can remove modifiers using -?
or -readonly
.
type Required<T> = {
[K in keyof T]-?: T[K];
};
type Mutable<T> = {
-readonly [K in keyof T]: T[K];
};
📌 These mimic TypeScript’s built-in Required<T>
and Mutable<T>
(from libraries like utility-types
).
💡 Example 5: Combining with Conditional Types
type BooleanMap<T> = {
[K in keyof T]: T[K] extends boolean ? "toggle" : "input";
};
type FormControls = {
subscribe: boolean;
email: string;
};
type ControlTypes = BooleanMap<FormControls>;
🔍 Output:
// ControlTypes becomes:
{
subscribe: "toggle";
email: "input";
}
🧠 Use cases: dynamically rendering form elements or UI controls based on property types.
🧬 Example 6: Remapping Keys with as
You can rename keys using as
(introduced in TypeScript 4.1+):
type Getters<T> = {
[K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
};
type Product = {
id: number;
name: string;
};
type ProductGetters = Getters<Product>;
🔍 Output:
{
getId: () => number;
getName: () => string;
}
📌 This is highly useful for generating dynamic method names in APIs or UI frameworks.
🧰 Common Use Cases for Mapped Types
Use Case | Example |
---|---|
Make fields optional | Partial<T> |
Make fields required | Required<T> |
Readonly object config | Readonly<T> |
Rename fields dynamically | Using as in mapped types |
Conditional field transformation | Combining with T[K] extends U ? ... |
Create DTOs or API models | Convert client types for backend |
📌 Summary – Recap & Real-World Relevance
Mapped types in TypeScript are essential for writing clean, scalable, and reusable code. They empower you to construct new types from existing ones with minimal repetition and maximum control.
🔍 Key Takeaways:
- Use
keyof
+in
to iterate over object properties. - Apply modifiers like
readonly
,optional
, or remove them using-?
,-readonly
. - Combine with conditional types for dynamic logic.
- Use
as
to rename keys programmatically.
⚙️ Real-world applications:
- Form builders & dynamic UI
- Redux state transformations
- API request/response shape mapping
- Component prop filtering and auto-generation
❓ FAQs
❓ What are mapped types?
✅ Mapped types allow you to create new types by looping over keys in an existing object type and transforming their values or modifiers.
❓ How are mapped types different from interfaces?
Mapped types are dynamic and can generate new types based on logic, whereas interfaces are static declarations of shape.
❓ Can mapped types work with union types?
Not directly. Mapped types work on object types
. To use with unions, you typically combine with conditional types or Extract<T, U>
.
❓ Are mapped types used in utility types?
Yes. Built-in types like Partial<T>
, Required<T>
, Readonly<T>
, and even Pick<T, K>
internally use mapped type syntax.
Share Now :