Union & Intersection Types
Why union and intersection types matter
Real-world applications rarely deal with perfectly uniform data. Values can be one of several possible types, or they may combine multiple type contracts. Union and intersection types allow you to model these scenarios precisely, without sacrificing safety.
Union types
A union type represents a value that can be one of multiple types. Use the | operator to define unions.
let id: number | string; id = 10; // OK id = "A-100"; // OK
Union types are ideal when modeling flexible inputs, such as API parameters or form values.
Narrowing union types
When working with unions, you must narrow the type before accessing specific properties or methods.
function printId(id: number | string) {
if (typeof id === "string") {
console.log(id.toUpperCase());
} else {
console.log(id.toFixed(2));
}
}
TypeScript understands control flow and narrows the type automatically.
Union of object types
Union types can represent different object shapes.
type Success = { status: "success"; data: string };
type ErrorResult = { status: "error"; message: string };
type ApiResponse = Success | ErrorResult;
This pattern is common in API design and improves clarity.
Discriminated unions
A discriminated union uses a shared literal property to distinguish between variants safely.
function handleResponse(res: ApiResponse) {
if (res.status === "success") {
console.log(res.data);
} else {
console.error(res.message);
}
}
This approach makes exhaustive handling easier and safer.
Intersection types
An intersection type combines multiple types into one. Use the & operator.
type Timestamped = { createdAt: Date };
type User = { id: number; name: string };
type UserWithTimestamp = User & Timestamped;
The resulting type must satisfy both contracts simultaneously.
Intersection in layered models
Intersections are useful when layering concerns, such as combining domain entities with metadata or audit information.
type Auditable = { createdBy: string };
type SecureUser = User & Auditable;
Common mistakes
- Using unions without proper narrowing.
- Creating overly complex nested unions that reduce readability.
- Misusing intersections when a simpler object structure would be clearer.
Union vs intersection mental model
- Union: A value can be this OR that.
- Intersection: A value must be this AND that.
Production guidance
- Use discriminated unions for API result modeling.
- Use intersections for composable domain models.
- Keep types readable; clarity scales better than cleverness.
- Prefer explicit narrowing for safer control flow.
What’s next
Now that you can model flexible and composable types, the next step is learning how to override inferred types safely using type assertions.