What is union type?
In TypeScript, a union type allows a value to be one of several types. It's a powerful feature for handling values that can legitimately take on different forms, providing both flexibility and type safety.
What is a Union Type?
A union type describes a value that can be any one of several types. You create a union type using the vertical bar (pipe) symbol, |, between each type. For example, string | number means a value can be either a string or a number.
Union types are particularly useful when you have a variable, function parameter, or return value that can accept data of different, but known, types. TypeScript's type checker will ensure that you only perform operations valid for all types in the union (without narrowing), or it will guide you to narrow the type down before performing specific operations.
Syntax and Examples
Here's how you can define and use union types:
function printId(id: number | string) {
console.log("Your ID is: " + id);
// Type narrowing: Check the type before performing type-specific operations
if (typeof id === "string") {
console.log(id.toUpperCase()); // Valid because 'id' is now known to be a string
} else {
console.log(id * 2); // Valid because 'id' is now known to be a number
}
}
printId(101); // Works
printId("202"); // Works
// printId(true); // Error: Argument of type 'boolean' is not assignable to parameter of type 'string | number'.
let userId: number | string | boolean;
userId = 123;
userId = "abc";
userId = true;
// userId = []; // Error: Type '[]' is not assignable to type 'string | number | boolean'.
In the example above, the printId function accepts an id that can be either a number or a string. Inside the function, we use typeof checks to 'narrow' the type of id, allowing us to call type-specific methods like toUpperCase() for strings or perform arithmetic operations for numbers.
Key Benefits
- Flexibility: Allows variables or parameters to accept data of multiple types.
- Type Safety: TypeScript ensures that you only perform operations valid for all types in the union (without narrowing), preventing common runtime errors.
- Improved Readability: Clearly communicates that a value can be one of a specific set of types, making code easier to understand.
- Type Narrowing: Works seamlessly with control flow analysis (like
ifstatements withtypeoforinstanceof) to allow type-specific operations within branches.
Discriminated Unions (Advanced)
For more complex scenarios, especially when dealing with objects that can have different shapes based on a common property, TypeScript offers 'discriminated unions'. This pattern uses a literal property (the 'discriminant') to tell TypeScript which specific type within a union an object is, enabling even more robust type narrowing and exhaustive checks.