- Abstract class
- Annotations
- Array
- Asserts
- Class
- Const
- Decorators
- Default parameter
- Dictionary
- Enum
- For loop
- forEach()
- Function
- Generics
- Index signature
- Infer
- Inheritance
- Interface
- Let
- Map type
- Mixin
- Module
- Namespace
- Never
- Object type
- Operator
- Optional parameter
- Promise
- Property
- Tuples
- Type alias
- Type guard
- Type narrowing
- Union
- Utility types
- Var
- Void
TYPESCRIPT
TypeScript Map Type: Syntax, Usage, and Examples
TypeScript map types let you transform the properties of an existing type into a new type. You can modify properties by changing their types, making them optional, readonly, or even renaming them dynamically. This feature is useful when you need to create flexible, reusable types without rewriting the same structure multiple times.
Quick Answer: What is a Mapped Type in TypeScript?
A mapped type in TypeScript is a generic type that creates a new type by iterating over the properties (keys) of an existing type. It allows you to transform each property in the original type, for example, by making it readonly
or optional
. This is a powerful feature for creating reusable utility types.
Syntax:
type NewType = {
[Property in keyof OriginalType]: TransformedType;
};
Example: Creating a Readonly
version of a type
// Original type
interface User {
name: string;
age: number;
}
// Mapped type that makes all properties of User readonly
type ReadonlyUser = {
readonly [K in keyof User]: User[K];
};
const user: ReadonlyUser = {
name: "Alice",
age: 30,
};
// user.name = "Bob"; // Error! Cannot assign to 'name' because it is a read-only property.
This is different from the Map
data structure. A mapped type is a feature for transforming types, whereas Map
is a data structure for storing key-value data.
How to Use Map Types in TypeScript
You define a map type using the keyof
operator to iterate over an existing type’s keys and apply transformations. Here’s the basic syntax:
type Mapped<T> = {
[K in keyof T]: T[K];
};
This mapped type takes every key K
from T
and keeps the same type for each key. You can modify this structure to change property behavior.
Example: Making Properties Readonly
You can use mapped types to make object properties readonly:
type User = {
name: string;
age: number;
};
type ReadonlyUser = {
readonly [K in keyof User]: User[K];
};
const user: ReadonlyUser = {
name: "Alice",
age: 30
};
user.name = "Bob"; // Error: Cannot assign to 'name' because it is a read-only property
In this example, ReadonlyUser
ensures that name
and age
cannot be modified after assignment.
Using Generic Mapped Types
By adding generics, you make your mapped types more flexible:
type MakeOptional<T> = {
[K in keyof T]?: T[K];
};
type OptionalUser = MakeOptional<User>;
const user2: OptionalUser = {
name: "Alice"
}; // 'age' is now optional
This generic mapped type lets you make all properties optional dynamically.
When to Use Map Types in TypeScript
You should use map types when you need to modify an object’s structure without duplicating code. They help when creating utility types for transformations like making properties optional, readonly, or converting types. You can also use them for API response handling, data validation, and object transformations.
Map types ensure that your modifications remain type-safe. If you want to map one type to another while preserving property names, map types provide a structured way to enforce these rules.
Examples of Map Types in TypeScript
Making All Properties Optional
You can make every property in a type optional:
type Partial<T> = {
[K in keyof T]?: T[K];
};
type UserPartial = Partial<User>;
const user3: UserPartial = {
name: "John"
}; // 'age' is optional
This is helpful when handling objects that don’t always require every property.
Making All Properties Required
Conversely, you can enforce that all properties must be present:
type Required<T> = {
[K in keyof T]-?: T[K];
};
type UserRequired = Required<User>;
const user4: UserRequired = {
name: "Eve",
age: 25
}; // Error if any property is missing
By using -?
, you remove the optional modifier from all properties.
Changing All Property Types
You can convert every property in an object to a specific type:
type ConvertToStrings<T> = {
[K in keyof T]: string;
};
type UserStrings = ConvertToStrings<User>;
const user5: UserStrings = {
name: "Alice",
age: "30"
};
This transformation ensures that all values in UserStrings
are now string
instead of their original types.
Mapping an Array to an Object Type
Map types also work with arrays when converting their structure:
type ArrayToObject<T> = {
[K in keyof T]: T[K];
};
type UserArray = ArrayToObject<User[]>;
const users: UserArray = [
{ name: "Alice", age: 30 },
{ name: "Bob", age: 25 }
];
This keeps the user array properly typed.
Learn More About TypeScript Map Types
Mapping a Union Type
You can map union types to different values dynamically:
type Status = "success" | "error" | "loading";
type StatusMessages = {
[K in Status]: string;
};
const messages: StatusMessages = {
success: "Operation completed",
error: "An error occurred",
loading: "Processing..."
};
Now, every possible status has a corresponding message.
Using Conditional Types with Mapped Types
You can combine mapped types with conditional types for more precise transformations:
type Conditional<T> = {
[K in keyof T]: T[K] extends string ? boolean : number;
};
type UserConditional = Conditional<User>;
const user6: UserConditional = {
name: true, // Converted from string to boolean
age: 30 // Remains a number
};
This structure automatically changes string
properties to boolean
, leaving number
properties unchanged.
Extending and Declaring Map Types
If you need to extend an existing type while renaming properties, you can use mapped types dynamically:
type BaseUser = {
id: number;
name: string;
};
type ExtendedUser = BaseUser & {
[K in keyof BaseUser as `meta_${K}`]: string;
};
const user7: ExtendedUser = {
id: 1,
name: "Alice",
meta_id: "user-1",
meta_name: "meta-Alice"
};
This type creates new properties prefixed with meta_
while keeping the original ones.
TypeScript map types give you the power to transform object structures dynamically. You can make properties optional, enforce readonly constraints, change types, and create reusable type utilities.
Looking to dive deeper into TypeScript map types and other essential TypeScript concepts? Check out our TypeScript course.
Key Takeaways for TypeScript Mapped Types
- Creates New Types from Existing Types: The main purpose of a mapped type is to take an existing type and create a new one by transforming its properties.
- Core Syntax is
[K in keyof T]
: This syntax iterates over every key (K
) in a given type (T
), allowing you to define a new type for each property. - Add or Remove Modifiers: You can easily add modifiers like
readonly
or?
(optional), or remove them withreadonly
and?
. - Enables Reusable Utility Types: This pattern is the foundation for many of TypeScript's most useful built-in utility types, like
Partial<T>
,Readonly<T>
, andRequired<T>
. - Different from the
Map
Data Structure: Do not confuse mapped types, which are a type-level feature for defining shapes, with theMap
object, which is a runtime data structure for storing key-value pairs.
Sign up or download Mimo from the App Store or Google Play to enhance your programming skills and prepare for a career in tech.