TypeScript Tutorial: Union & Intersection Types
Combine types with | (union) and & (intersection), and use type aliases for reusable type definitions.
Type Aliases
A `type` alias gives a name to any type:
```typescript
type ID = string | number;
type Point = { x: number; y: number };
type Callback = (error: Error | null, result: string) => void;
```
---
Union Types
A union type `A | B` means a value can be **either** type:
```typescript
type Status = "pending" | "active" | "inactive";
type StringOrNumber = string | number;
function format(value: StringOrNumber): string {
if (typeof value === "number") {
return value.toFixed(2);
}
return value.trim();
}
console.log(format(3.14159)); // "3.14"
console.log(format(" hello ")); // "hello"
```
---
Literal Types
Restrict a value to specific literals:
```typescript
type Direction = "north" | "south" | "east" | "west";
type DiceRoll = 1 | 2 | 3 | 4 | 5 | 6;
function move(dir: Direction) {
console.log(`Moving ${dir}`);
}
move("north"); // ✓
move("up"); // ✗ Error: not a valid Direction
```
---
Intersection Types
An intersection type `A & B` means a value must be **both** types:
```typescript
interface Timestamped {
createdAt: Date;
updatedAt: Date;
}
interface Named {
name: string;
}
type NamedRecord = Named & Timestamped;
const record: NamedRecord = {
name: "Alice",
createdAt: new Date(),
updatedAt: new Date(),
};
```
---
Discriminated Unions
A pattern for handling different shapes safely:
```typescript
type Circle = { kind: "circle"; radius: number };
type Square = { kind: "square"; side: number };
type Shape = Circle | Square;
function area(shape: Shape): number {
switch (shape.kind) {
case "circle": return Math.PI * shape.radius ** 2;
case "square": return shape.side ** 2;
}
}
```
---
What's Next?
Next: **Generics** — write functions and types that work with any type while staying type-safe.
What you'll learn in this TypeScript union & intersection types tutorial
This interactive TypeScript tutorial has 12 hands-on exercises. Estimated time: 10 minutes.
- Union types — either/or values — A union type `A | B` means a value can be type A or type B. You must narrow it before using type-specific methods.
- Literal union types — closed sets of values — A union of literal types restricts values to a specific set. TypeScript ensures only valid values are used.
- Discriminated unions — type-safe variants — A discriminated union uses a shared `kind` or `type` field to distinguish variants. TypeScript narrows automatically in …
- Union with null — nullable values — `T | null` and `T | undefined` are the standard way to express optional values. TypeScript forces you to handle the miss…
- Union narrowing with type predicates — A function returning `value is Type` is a type guard — it narrows the type at the call site when it returns `true`.
- Intersection types — combine constraints — An intersection type `A & B` requires a value to satisfy BOTH types simultaneously. Use it to compose reusable type piec…
- Template literal union types — Template literal types generate all combinations of string literals. They're used for event names, CSS properties, and A…
- Mapped type from union — transform all variants — You can map over a union type to transform it, creating related types automatically.
- Union narrowing with switch exhaustion — Using `never` in the default case ensures all union variants are handled. Add a new variant and TypeScript errors if you…
- Tagged union vs enum — when each fits — Tagged unions and enums solve similar problems. Tagged unions are more flexible and idiomatic TypeScript; enums provide …
- Conditional types with unions — distributive behavior — Conditional types distribute over unions — applying to each member separately. This enables powerful type filtering.
- Union types in practice — real patterns — Union types are everywhere in real TypeScript codebases. Here's a practical example combining several patterns.
TypeScript Union & Intersection Types concepts covered
- Type Aliases
- Union Types
- Literal Types
- Intersection Types
- Discriminated Unions
- What's Next?