Skip to main content

What does "discriminated union" mean?

What a Discriminated Union is

A discriminated union is a union (union) of several object types where each type shares a common tag field (a discriminant) that unambiguously indicates which variant the object belongs to.

In other words: it is a union whose members all share a common property, and by its value TypeScript understands exactly which type it is dealing with.


Example 1. A simple discriminated union

javascript
type Shape = | { kind: "circle"; radius: number } | { kind: "square"; side: number }; function getArea(shape: Shape): number { if (shape.kind === "circle") { // Here shape: { kind: "circle"; radius: number } return Math.PI * shape.radius ** 2; } else { // Here shape: { kind: "square"; side: number } return shape.side ** 2; } }
  • The common field kind is the discriminant
  • TypeScript automatically narrows the type based on its value
  • You can safely access radius or side, without as and without errors

Why this is convenient

In a regular union type, TS does not know which specific object is being used:

javascript
type Circle = { radius: number }; type Square = { side: number }; type Shape = Circle | Square; function area(shape: Shape) { // shape.radius Error: Square has no radius }

If you add a common field (kind), TypeScript can figure out which is which on its own.


Example 2. Several type variants

javascript
type Shape = | { kind: "circle"; radius: number } | { kind: "square"; side: number } | { kind: "triangle"; base: 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 "triangle": return (shape.base * shape.height) / 2; } }

Inside each case, TypeScript knows exactly which fields are available, and suggests them in autocomplete.


Example 3. Exhaustiveness check

Discriminated unions let you control that all possible variants are handled (important when extending types):

javascript
function area(shape: Shape): number { switch (shape.kind) { case "circle": return Math.PI * shape.radius ** 2; case "square": return shape.side ** 2; case "triangle": return (shape.base * shape.height) / 2; default: // Error, if a new type appears without a case const _exhaustiveCheck: never = shape; return _exhaustiveCheck; } }

This way, if you add a new type (for example, "rectangle"), TS immediately shows that the switch no longer covers all variants.


Example 4. A real-world scenario (API response)

javascript
type ApiResponse = | { status: "success"; data: string } | { status: "error"; message: string } | { status: "loading" }; function handleResponse(res: ApiResponse) { switch (res.status) { case "success": console.log("Data:", res.data); break; case "error": console.error("Error:", res.message); break; case "loading": console.log("Loading..."); break; } }

A single discriminating key (status) fully describes the state. A very popular pattern in React code and Redux logic.


Rules for discriminated union types

RequirementDescription
A common field (discriminant)All variants must have the same property (for example, kind, type, status)
Unique valuesEach discriminant value is unique to its own variant
The field's type is a literalUsually a string literal ("circle", "error", "admin")
TS automatically narrows the typeAn if or switch check performs narrowing without casts

Discriminated union vs regular union

KindExampleCan TS narrow the type automatically?
Regular union{ radius: number } | { side: number }No
Discriminated union{ kind: "circle" } | { kind: "square" }Yes

Summary

TermMeaning
Discriminated unionA union of types with a shared "discriminating" field
Why it is neededSo TypeScript can precisely determine the type from the field's value
How it is denotedVia `
Main benefitSafe and convenient type narrowing without manual checks
Typical useStatuses, data shapes, API responses, shapes, component states

In short:

A discriminated union is a union of objects that share a common tag field (for example, kind), and by the value of that tag TypeScript automatically understands which type it is

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.