Learn TypeScript
Creating intersection types
Creating intersection types
In this lesson, we'll learn what an intersection type is and how to create one.
Understanding an intersection type
Intersection types, like union types, combine existing types to form a new type. An intersection type will have all the members from the types that it is based on. Intersection types don't just contain the common members from the types that it is based on, as you may first expect.
An intersection type is constructed from existing types using the ampersand (&
) character:
type A_and_B_and_C = A & B & C;
Let's go through an example to get confortable with intersection types:
The code combines Name
and PhoneNumber
types to create a Contact
type containing firstName
, lastName
, landline
and mobile
properties.
- Create a variable with our intersection type and assign the following value to it:
const fred: Contact = { firstName: "Fred", lastName: "Smith", landline: "0116 4238978", mobile: "079543 4355435",};
Is the TypeScript type checker okay with this assignment?
- Let's define another type called
Email
as follows:
type Email = { emailAddress: string;};
How could we add Email
to the Contact
type so that it contains the emailAddress
property? Make this change in the code editor.
A type error is now raised on the fred
variable. Why is this so?
- Include an email address in the
fred
value:
const fred: Contact = { firstName: "Fred", lastName: "Smith", landline: "0116 4238978", mobile: "079543 4355435", emailAddress: "fred.smith@someemail.com",};
The type error is now resolved.
Intersection of common members
What happens when we intersect types that have members with the same name? Let's carry out the following steps to find out:
- Add the following code into our code editor:
type BaseElement = { name: string; kind: "text" | "number" | "email";};type TextInput = { kind: "text";};type Field = BaseElement & TextInput;
This code creates a Field
type from the intersection of BaseElement
and TextInput
types:
- Creates an
age
variable from theField
type and assign a value to it:
const age: Field = { name: "Age", kind: "number",};
A type error occurs. Can you spot the problem?
The type of a common member of an intersection type is mathematically intersected.
- Now enter the code below where the common member of an intersection type is a function:
type A = { doIt: (a: string) => void;};type B = { doIt: (a: string, b: string) => void;};type A_and_B = A & B;
- Add the following variable of this intersection type and give it the following value:
const ab_v1: A_and_B = { doIt: (a: string) => {},};
Is a type error raised?
- Now try the following variable assignment:
const ab_v2: A_and_B = { doIt: (a: string, b: string) => {},};
Is a type error raised?
The parameters of a common function member of an intersection type are mathematically intersected.
Summary
In this lesson, we have seen how type aliases can extend existing types using the intersection operator. It is a common misconception that interfaces are more powerful than type aliases because interfaces can be extended, but we now understand that this is possible in type aliases as well.
Now that we have a good understanding of type aliases and interfaces, we will compare them in the next lesson.