Union and Intersection Types
Union and Intersection Types
Union types (|)
A union type means a value can be one of several types:
type StringOrNumber = string | number;You must narrow the type before using type-specific operations.
Intersection types (&)
An intersection combines multiple types into one, requiring all members to be present:
type Admin = User & { role: "admin" };Discriminated unions
Add a common literal-type field (the discriminant) to each member of a union. TypeScript's control-flow analysis then narrows the type automatically inside if or switch blocks.
Type narrowing
typeof– narrows primitive types ("string","number","boolean","object","function", etc.).instanceof– narrows class instances.inoperator – narrows by checking property presence.- Assignment and truthiness checks also narrow types.
Best practice: prefer discriminated unions over ad-hoc typeof checks for complex variant types.
Code Examples
function formatId(id: string | number): string {
if (typeof id === "string") {
return id.toUpperCase();
}
return id.toFixed(0);
}
console.log(formatId("abc-123"));
console.log(formatId(42));Inside the if branch TypeScript knows id is string, so toUpperCase() is safe. After the branch it is number.
type Circle = { kind: "circle"; radius: number };
type Rectangle = { kind: "rect"; width: number; height: number };
type Shape = Circle | Rectangle;
function area(shape: Shape): number {
switch (shape.kind) {
case "circle":
return Math.PI * shape.radius ** 2;
case "rect":
return shape.width * shape.height;
}
}
console.log(area({ kind: "circle", radius: 5 }).toFixed(2));
console.log(area({ kind: "rect", width: 4, height: 6 }));The kind discriminant lets TypeScript narrow the type in each case branch, giving you full access to the right properties.
type Timestamped = { createdAt: Date };
type Named = { name: string };
type Entity = Timestamped & Named & { id: number };
function createEntity(name: string): Entity {
return { id: Math.random(), name, createdAt: new Date() };
}
const e = createEntity("Product");
console.log(e.name);
console.log(typeof e.createdAt);
console.log(typeof e.id);Intersection types compose multiple shapes. An Entity must satisfy all three constituent types simultaneously.
Quick Quiz
1. What is a discriminated union?
2. What does `A & B` mean in TypeScript?
Was this lesson helpful?