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:

TypeScriptOpen exercise in CodeSandbox

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 the Field 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.

Did you find this lesson useful?

Share this lesson on twitter
© 2023 Carl Rippon
Privacy Policy
This site uses cookies. Click here to find out more