Discriminated Unions
Modeling object variants with one shared literal field that TypeScript can narrow.
A discriminated union is a union of objects that share one literal field. TypeScript reads that field to know which case it has.
Start with a shared kind field. Each literal value brings its own required fields.
type Shape =
| { kind: "circle"; radius: number }
| { kind: "rect"; width: number; height: number }
| { kind: "label"; text: string };
const badge: Shape = { kind: "circle", radius: 12 };
const title: Shape = { kind: "label", text: "Ready" };Checking shape.kind narrows the value inside each branch.
function describe(shape: Shape): string {
switch (shape.kind) {
case "circle":
return `circle with radius ${shape.radius}`;
case "rect":
return `rectangle ${shape.width}x${shape.height}`;
case "label":
return `label: ${shape.text}`;
}
}In production
Discriminated unions are the normal TypeScript shape for events, commands,
reducer actions, state machines, and API responses. Use an exact tag, keep
the required fields beside it, and add a never check when missing a case
would be a bug.
Enjoyed this? Get more software craft delivered to your inbox.