Table of Contents
- Introduction
- What Are Union Types?
- Syntax of Union Types
- Example Code: Union Types
- Practical Use Cases of Union Types
- What Are Intersection Types?
- Syntax of Intersection Types
- Example Code: Intersection Types
- Practical Use Cases of Intersection Types
- Comparison Between Union and Intersection Types
- Conclusion
Introduction
TypeScript’s powerful type system allows developers to work with more advanced concepts that enhance code safety and maintainability. Among these advanced features, union types and intersection types are two of the most commonly used concepts for combining multiple types into a single type. Understanding how they work, and when to use them, is crucial for writing efficient and type-safe TypeScript code.
In this article, we will take a deep dive into union types and intersection types, explain their syntax, explore practical use cases, and compare them to help you decide when to use one over the other.
What Are Union Types?
Union types in TypeScript allow you to define a variable that can hold values of more than one type. You specify the possible types a variable can have by separating them with a vertical bar (|
). A union type is useful when a variable can accept different types depending on the scenario, but you want to limit the options to a set of types.
Syntax of Union Types
The syntax for union types is simple: you use the pipe (|
) operator to separate multiple types.
type UnionType = Type1 | Type2;
Example Code: Union Types
Let’s look at a practical example:
function getLength(input: string | number): number {
if (typeof input === "string") {
return input.length; // TypeScript knows input is a string
} else {
return input.toString().length; // TypeScript knows input is a number
}
}
console.log(getLength("Hello, World!")); // Output: 13
console.log(getLength(12345)); // Output: 5
In this example, the input
parameter can either be a string
or a number
. Depending on the type of input
, the function calculates the length differently: if it’s a string, it uses the .length
property, and if it’s a number, it converts it to a string and calculates the length of that string.
Practical Use Cases of Union Types
Union types are commonly used in situations where a value can take on more than one type. Some practical use cases include:
- Handling multiple possible input types: Functions that can accept strings, numbers, or even objects.
- Handling error types: When a function can either return a success value or an error message, you can use union types to represent both possibilities.
- Working with optional parameters: Union types can be used to define an optional parameter (
undefined
as one of the types).
type Success = { success: true, data: string };
type Error = { success: false, error: string };
function fetchData(): Success | Error {
// Simulate a random outcome (for example purposes)
if (Math.random() > 0.5) {
return { success: true, data: "Data fetched successfully" };
} else {
return { success: false, error: "Failed to fetch data" };
}
}
What Are Intersection Types?
Intersection types in TypeScript allow you to combine multiple types into one. This means that the resulting type will have all the properties and methods of each of the combined types. Intersection types are useful when you want to ensure that a variable or parameter conforms to multiple types at once.
Syntax of Intersection Types
The syntax for intersection types is simple: you use the ampersand (&
) operator to combine types.
type IntersectionType = Type1 & Type2;
Example Code: Intersection Types
Let’s see an example where we combine two types to form a new one:
type Person = { name: string, age: number };
type Employee = { jobTitle: string, salary: number };
type EmployeePerson = Person & Employee;
const employee: EmployeePerson = {
name: "John Doe",
age: 30,
jobTitle: "Software Engineer",
salary: 80000,
};
console.log(employee);
In this example, the EmployeePerson
type is an intersection of the Person
and Employee
types. As a result, any object of type EmployeePerson
must have both name
and age
(from Person
) and jobTitle
and salary
(from Employee
).
Practical Use Cases of Intersection Types
Intersection types are used in scenarios where a value needs to conform to multiple types simultaneously. Some practical use cases include:
- Combining multiple objects: You can combine types to create objects that conform to multiple contracts.
- Enhancing functionality: When a class or object needs to combine the behavior of two different interfaces, you can use intersection types.
- Mixin functionality: When working with object-oriented programming or functional programming, intersection types allow you to mix different features or behaviors into a single type.
interface CanFly {
fly(): void;
}
interface CanSwim {
swim(): void;
}
class FlyingSwimmingAnimal implements CanFly, CanSwim {
fly() {
console.log("Flying");
}
swim() {
console.log("Swimming");
}
}
type FlyingSwimmingAnimalType = CanFly & CanSwim;
const duck: FlyingSwimmingAnimalType = new FlyingSwimmingAnimal();
duck.fly(); // Output: Flying
duck.swim(); // Output: Swimming
Comparison Between Union and Intersection Types
While union and intersection types may seem similar, they serve different purposes. Let’s compare them:
| Feature | Union Types (|
) | Intersection Types (&
) |
|—————–|—————————|—————————-|
| Definition | A type that can be one of several types | A type that must satisfy all specified types |
| Behavior | Accepts values from any of the types | Requires a value to have properties of all combined types |
| Use Case | When a value can be one of several types | When a value needs to conform to multiple types simultaneously |
| Syntax | type X = Type1 | Type2;
| type Y = Type1 & Type2;
|
| Example | let value: string | number;
| let value: Person & Employee;
|
Conclusion
Union types and intersection types are two powerful tools in TypeScript that allow developers to create more flexible and robust code.
- Union types allow a variable to be one of several types, making them ideal for cases where the value could be one of multiple possibilities. They are best used when you want to define flexible function parameters or return types.
- Intersection types combine multiple types into one, ensuring the value satisfies all of the types’ properties and behaviors. They are useful when you want to create more complex structures that need to conform to multiple interfaces or types.
Understanding when to use each type is key to writing maintainable and type-safe TypeScript code. By mastering union and intersection types, you’ll be able to handle more complex data structures with ease and improve the reliability of your codebase.