How to use discriminated unions in TypeScript
· Category: TypeScript
Short answer
A discriminated union is a union of object types that share a common literal property (the discriminant), enabling exhaustive type narrowing with switch statements.
Steps
- Define a shared discriminant:
type Shape = { kind: 'circle'; radius: number } | { kind: 'square'; side: number }; - Narrow with a switch:
switch (shape.kind) { case 'circle': return Math.PI * shape.radius ** 2; ... } - Use a default case with a helper that accepts
neverto enforce exhaustiveness. - Keep the discriminant a required literal string for reliable narrowing.
- Avoid optional discriminants because they break narrowing guarantees.
Tips
- Discriminated unions are ideal for Redux actions, state machines, and API result types.
- The exhaustiveness check ensures you handle every variant when adding new cases.
Common issues
- Using a non-literal type for the discriminant prevents TypeScript from narrowing correctly.
- Forgetting to handle a case causes compile errors if you implement an exhaustive check helper.