Understanding TypeScript Mapped Types
Discover how Mapped Types and Utility Types work in TypeScript.
Getting Started with TypeScript Mapped Types
TypeScript, the superhero of JavaScript with static typing, has a cool feature called mapped types. These let you transform existing types into new ones, saving time and reducing errors. Let’s break it down.
What are Mapped Types?
Mapped types let you create new types by transforming the properties of existing ones. Think of it as making a copy of a type but with some changes.
Simple Syntax
Here’s a basic way to understand it:
type MappedType<T> = {
[Key in keyof T]: SomeTransformation<T[Key]>;
};
T
is your original type.Key in keyof T
means you go through each property inT
.SomeTransformation<T[Key]>
is where you apply your change to each property.
Practical Examples
Let’s see some real-world examples to make this clearer.
- Making All Properties Optional
If you want to make every property in a type optional, use Partial
:
type Partial<T> = {
[Key in keyof T]?: T[Key];
};
Example:
interface User {
name: string;
age: number;
}
type OptionalUser = Partial<User>;
// Result: { name?: string; age?: number; }
In OptionalUser
, both name
and age
are now optional.
- Making All Properties Read-Only
To make every property read-only, use Readonly
:
type Readonly<T> = {
readonly [Key in keyof T]: T[Key];
};
Example:
type ReadonlyUser = Readonly<User>;
// Result: { readonly name: string; readonly age: number; }
In ReadonlyUser
, you can’t change name
or age
once they’re set.
- Changing All Property Types to
string
If you need every property to be a string
, use this:
type Stringify<T> = {
[Key in keyof T]: string;
};
Example:
type StringifiedUser = Stringify<User>;
// Result: { name: string; age: string; }
In StringifiedUser
, both name
and age
are now string
types.
- Making All Properties Nullable
To make each property null
or its original type, use Nullable
:
type Nullable<T> = {
[Key in keyof T]: T[Key] | null;
};
Example:
type NullableUser = Nullable<User>;
// Result: { name: string | null; age: number | null; }
In NullableUser
, name
and age
can now also be null
.
- Creating a Type for Full Names
Let's create a mapped type where keys can be anything, and all values are string
:
type GiveMeaningFullName = {
[key: string]: string;
};
Example:
const userFullNames: GiveMeaningFullName = {
firstName: "John",
lastName: "Doe",
nickname: "Johnny"
};
// Result: { firstName: "John", lastName: "Doe", nickname: "Johnny" }
In GiveMeaningFullName
, you can have any key as long as the value is a string
.
Why Use Mapped Types?
Reusability: Write a transformation once, use it everywhere.
Consistency: Keep all your type changes uniform.
Clarity: Your code becomes easier to understand and maintain.
Conclusion
Mapped types are a fantastic feature in TypeScript that help you transform types easily. Whether you need optional properties, read-only properties, or different types altogether, mapped types make it simple.
Try using mapped types in your next TypeScript project and see how they can make your code cleaner and more manageable!