Background:
Union types emerged in TypeScript to describe variables and parameters that can have values of different types. This capability significantly expanded the flexibility of typing compared to classical languages.
Problem:
In JavaScript, functions and variables are often multi-format (for example, accepting either a number or a string), which complicates safe typing. Without union types, it was necessary to use any or duplicate code. This increased the number of errors in production and made teamwork more difficult in large teams.
Solution:
Union types allow declaring a variable that can be one of several types, ensuring correct operations after checks. Type narrowing support is also implemented, helping the compiler "understand" what it is dealing with.
Example code:
function formatId(id: number | string): string { if (typeof id === 'string') { return id.toUpperCase(); } return id.toString(); }
Key features:
Can you write a union of objects with different properties and access any property without a check?
No. Union types allow you to access only those properties and methods that are present in all types. Accessing private properties requires type narrowing.
Example code:
type Fish = { swim: () => void; }; type Bird = { fly: () => void; }; function move(animal: Fish | Bird) { // animal.swim(); // Error without narrowing if ('swim' in animal) { animal.swim(); // OK } }
Why are not all methods available for the union type string | number?
TypeScript in union only allows what is present in all included types. Individual methods need to be checked for the actual type first.
What happens if you don’t check the type in a union and try to call a specific method?
In that case, a compilation error will occur, as the presence of the method is not guaranteed. It only works after checking the specific type.
A variable was given the type string | number and toUpperCase() was called without a check. As a result, the application crashes on numeric data.
Pros:
Cons:
Check the type before working with the method:
if (typeof value === 'string') { return value.toUpperCase(); } else { return value.toString(); }
Pros:
Cons: