Questions
What are mapped types and how do you use them in TypeScript?
The Scenario
You are a frontend engineer at a social media company. You are writing a new function that needs to take an object and return a new object with all the properties of the original object set to readonly.
You could create a new type with all the properties set to readonly by hand, but this would be repetitive and would violate the DRY (Don’t Repeat Yourself) principle.
The Challenge
Explain what mapped types are in TypeScript and how you would use them to solve this problem. What are the key benefits of using mapped types?
A junior engineer might not be aware of mapped types. They might try to solve this problem by creating a new type with all the properties set to `readonly` by hand, which would be a verbose and difficult to maintain solution.
A senior engineer would know that mapped types are the perfect tool for this job. They would be able to explain what mapped types are and how to use them to create new types from existing types.
Step 1: Understand What Mapped Types Are
A mapped type is a generic type which uses a union of PropertyKeys (frequently created by a keyof) to iterate through keys to create a type.
Step 2: Write a Simple Mapped Type
Here’s how we can write a simple mapped type to create a new type with all the properties of an existing type set to readonly:
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};This is the actual implementation of the built-in Readonly<T> utility type.
Step 3: Use the Mapped Type
We can use the mapped type with any type:
interface User {
id: number;
name: string;
}
type ReadonlyUser = Readonly<User>;
const user: ReadonlyUser = {
id: 1,
name: "John Smith"
};
// This will raise an error
// user.id = 2;The Benefits of Using Mapped Types
| Benefit | Description |
|---|---|
| Reusability | You can reuse the same mapped type with a variety of different types. |
| Maintainability | You can change the properties of all the types that use a mapped type by just changing the mapped type. |
Practice Question
You want to create a new type that has all the properties of an existing type, but with all the properties set to optional. Which of the following would you use?