Intersection Types in TypeScript
This article explains intersection types in TypeScript.
YouTube Video
Intersection Types in TypeScript
In TypeScript, intersection types are a way to combine multiple types to create a new type.
What are Intersection Types?
Intersection types allow you to combine multiple types to define a new type with all properties of those types. Intersection types are defined using the &
symbol and require all properties from each constituent type.
Example:
1type A = { name: string };
2type B = { age: number };
3
4type C = A & B;
5
6const person: C = {
7 name: "John Doe",
8 age: 30
9};
In this code, by defining type C = A & B
, the C
type becomes an object type that has both name
and age
.
Benefits of Intersection Types
By using intersection types, you can reuse existing types and define more flexible and composite types. This enhances the maintainability and extensibility of your code. Additionally, intersection types can apply constraints of multiple different types simultaneously, thereby enhancing type safety.
Benefits:
- Reusability: By combining multiple types, you can reduce redundant definitions and reuse existing types.
- Type Safety: Intersection types enhance type checking by allowing only objects that satisfy conditions of multiple types.
Use Cases for Intersection Types
Intersection types are extremely useful when extending objects or interfaces. In particular, it is useful when you want to represent objects with multiple properties.
Use Case 1: Objects with Multiple Interfaces
1interface Drivable {
2 drive(): void;
3}
4
5interface Flyable {
6 fly(): void;
7}
8
9type Vehicle = Drivable & Flyable;
10
11const car: Vehicle = {
12 drive() {
13 console.log("Driving on the road");
14 },
15 fly() {
16 console.log("Flying in the sky");
17 }
18};
19
20car.drive(); // "Driving on the road"
21car.fly(); // "Flying in the sky"
In this example, the Vehicle
type is defined as an intersection type combining Drivable
and Flyable
. An object of type Vehicle
must implement both the drive()
and fly()
methods.
Use Case 2: Combining Classes and Intersection Types
By combining classes and intersection types, it is possible to create objects that have the properties of multiple interfaces.
1interface Person {
2 name: string;
3}
4
5interface Employee {
6 employeeId: number;
7}
8
9type PersonEmployee = Person & Employee;
10
11class CompanyWorker implements PersonEmployee {
12 constructor(public name: string, public employeeId: number) {}
13
14 getDetails() {
15 return `${this.name}, Employee ID: ${this.employeeId}`;
16 }
17}
18
19const worker = new CompanyWorker("Alice", 123);
20console.log(worker.getDetails()); // "Alice, Employee ID: 123"
Here, we use the intersection type PersonEmployee
of Person
and Employee
to make the CompanyWorker
class have the properties of both.
Points to Consider with Intersection Types
An important point when using intersection types is to be aware of the possibility of property conflicts. If properties with the same name have different type annotations across different types, an error may occur.
Example of Caution:
1type A = { id: number };
2type B = { id: string };
3
4type C = A & B;
5
6// Error: Type 'number' and 'string' are not compatible
7const obj: C = {
8 id: 1
9};
In this example, the id
properties of A
and B
conflict, causing an error when defining an object with type C
. In such cases, a design review is necessary to avoid property conflicts.
Code Example with Type Annotations for Intersection Types
Finally, here is a real code example that includes type annotations.
Example 1: Displaying Object Details
1type ContactInfo = { phone: string; email: string };
2type Address = { city: string; postalCode: string };
3
4type PersonDetails = ContactInfo & Address;
5
6const details: PersonDetails = {
7 phone: "123-4567",
8 email: "example@mail.com",
9 city: "New York",
10 postalCode: "10001"
11};
12
13console.log(details);
- This code combines the
ContactInfo
andAddress
interfaces to create a new type calledPersonDetails
.
Example 2: Object with Additional Properties
1interface BasicInfo {
2 name: string;
3 age: number;
4}
5
6interface WorkInfo {
7 company: string;
8 position: string;
9}
10
11type FullInfo = BasicInfo & WorkInfo;
12
13const employee: FullInfo = {
14 name: "Bob",
15 age: 28,
16 company: "Tech Corp",
17 position: "Engineer"
18};
19
20console.log(`${employee.name} is a ${employee.position} at ${employee.company}`);
- This code combines the
BasicInfo
andWorkInfo
interfaces to create a new type calledFullInfo
.
Conclusion
TypeScript's intersection types are a powerful feature for combining multiple types into a new type. This enhances code reusability and safety, enabling complex type definitions. By effectively leveraging design flexibility while being cautious of type conflicts, you can achieve robust and highly readable code.
You can follow along with the above article using Visual Studio Code on our YouTube channel. Please also check out the YouTube channel.