Lesson 10 of 20

Union & Intersection Types

Union Types

A union type allows a value to be one of several types. Use the pipe (|) operator to combine types.

Example
// Union type
type StringOrNumber = string | number;

function display(value: StringOrNumber) {
  if (typeof value === "string") {
    console.log(value.toUpperCase());
  } else {
    console.log(value.toFixed(2));
  }
}

display("hello"); // "HELLO"
display(3.14);    // "3.14"

// Literal union types
type Status = "active" | "inactive" | "pending";
let userStatus: Status = "active";

Discriminated Unions

Discriminated unions use a common property to distinguish between variants. This is a powerful pattern for modeling data.

Example
type Shape =
  | { kind: "circle"; radius: number }
  | { kind: "square"; side: number }
  | { kind: "rectangle"; width: number; height: number };

function area(shape: Shape): number {
  switch (shape.kind) {
    case "circle":
      return Math.PI * shape.radius ** 2;
    case "square":
      return shape.side ** 2;
    case "rectangle":
      return shape.width * shape.height;
  }
}

console.log(area({ kind: "circle", radius: 5 })); // 78.54

Intersection Types

Intersection types combine multiple types into one. A value must satisfy all combined types.

Example
type HasName = { name: string };
type HasAge = { age: number };
type HasEmail = { email: string };

// Intersection: must have ALL properties
type Person = HasName & HasAge;
type Contact = Person & HasEmail;

const contact: Contact = {
  name: "Alice",
  age: 25,
  email: "alice@example.com"
};

// Practical: extending API responses
type ApiResponse<T> = {
  status: number;
  timestamp: string;
} & T;

type UserResponse = ApiResponse<{ user: { name: string } }>;