TypeScript theorytheory 0/50 · 0%
Types · medium

21. Discriminated unions

Tagged unions that make exhaustive handling safe.

A discriminated union gives each member of a union a shared literal-type field (the 'tag' or 'discriminant'), letting TypeScript narrow precisely based on that field.

ts
type Action =
  | { type: "deposit"; amount: number }
  | { type: "withdraw"; amount: number }
  | { type: "transfer"; to: string; amount: number };

function apply(a: Action): string {
  switch (a.type) {
    case "deposit": return `+${a.amount}`;
    case "withdraw": return `-${a.amount}`;
    case "transfer": return `-> ${a.to}: ${a.amount}`;
  }
}

Inside each `case`, TypeScript narrows `a` to exactly that variant, so `a.to` is only accessible in the `"transfer"` branch. This pattern scales well for modelling transaction types, wallet events, or reducer actions.

Check your understanding

  1. 1. What is the 'discriminant' in a discriminated union?

  2. 2. Inside `case "transfer":`, what does TypeScript know about `a`?

  3. 3. Why use discriminated unions over a single object with many optional fields?