Learn TypeScript
Creating a mapped type
Creating a mapped type
In this lesson, we will learn what mapped types are and how to create them.
Understanding a mapped type
A mapped type is the process of creating a new type by mapping type information from an existing type.
type MappedTypeName = { [K in UnionType]: ExistingType };
The in
operator maps over each item in the union type to create a new type. In other words, the in
operator allows us to loop through each type in a union type. In a loop iteration, wach item in the union type is put in K
, which becomes a key in the new type. So, the union type is usually a union of string literals. The type annotation in the mapped type is the type given to each key in the type.
So:
type ContactDetails = { [K in "name" | "email"]: string };
... creates the following type:
{ name: string; email: string;}
This becomes more useful when used with the keyof
operator we learned about in the last lesson:
type MappedTypeName = { [K in keyof ExistingType1]: ExistingType2;};
This creates a new type containing the keys from another type.
An example
We are going to explore a useful example of a mapped type in the code editor below:
The editor contains a generic Form
interface and a contactForm
variable that uses this interface for its type.
Can you spot a problem with the object assigned to contactForm
?
Why doesn't a type error occur to surface this problem?
- Update the
errors
type within theForm
interface to use a mapped type based onT
:
interface Form<T> { ... errors: { [K in keyof T]: string };}
- A type error is now raised on
emailAddress
, which a great. So, change this toemail
.
A type error still exists on errors
. What is the problem?
- The problem can be resolved if we make the mapped keys optional in the errors type. Update the mapped type so that its keys are optional by placing a question mark (
?
) in front of the key's type annotation.
All the type errors are now resolved.
Great!
- Add another property in the type passed into
Form
:
const contactForm: Form<{ ... mobile: string;}> = { ...};
- Add a mobile number in the
values
object:
values: { ... mobile: "0745 6723432"},
- Add an error for
mobile
in theerrors
object. Type this out manually and notice the intellisense.
errors: { ... mobile: "You must add a mobile number"},
Notice that no type errors are raised.
Nice!
Summary
Mapped types allow us to create new types based on an existing type. They are useful for handling generic data in a strongly-typed manner.
In the next lesson, we will learn about using type modifiers in mapped types.