State machines
Representing finite states such as loading, success, and failure, with each state carrying different data.
TypeScript · Function
A discriminated union is a union of object variants sharing a literal-typed tag, such as kind or state. TypeScript uses checks of that tag to narrow a value to the matching variant.
A discriminated union combines object variants that share a property whose type is a distinct literal in each variant. Checking that property with conditions or a switch lets TypeScript narrow the value to the matching object type, making variant-specific fields available while rejecting fields that are not shared.
type Union =
| { tag: "first"; firstData: First }
| { tag: "second"; secondData: Second };type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; sideLength: number };
function area(shape: Shape): number {
switch (shape.kind) {
case "circle":
return Math.PI * shape.radius ** 2;
case "square":
return shape.sideLength ** 2;
}
}
console.log(area({ kind: "circle", radius: 2 }));The literal kind value selects the union member, so each switch branch exposes only that member's specific property.
Representing finite states such as loading, success, and failure, with each state carrying different data.
Describing messages or events whose payload depends on a literal command or event name.
Modeling API results where success and failure responses expose different fields.
A discriminated union is a union whose members share a property with different literal types. Comparing that property narrows the value to the corresponding member, allowing access to its unique fields.
Follow-up: How can a switch detect an unhandled member? Add a default branch that assigns the remaining value to never; compilation then fails when the union is not exhausted.
Use a common field such as state with a literal type in each object variant. A switch or equality check on that field tells TypeScript which constituent remains, while the common field itself is safe to read before narrowing.
Follow-up: Why use literal types instead of string? Literal types prevent unrelated strings and misspellings from being treated as valid discriminant values.
A discriminated union can model alternatives such as network states or messages. Each alternative carries its own payload, and narrowing the tag ensures the payload is used with the correct variant.
Follow-up: What happens if code accesses a variant-only property before narrowing? TypeScript reports an error because that property is not guaranteed to exist on every constituent.
Union typesIntersection typesNarrowingLiteral typesThe never typeUnion exhaustiveness checking