AceDevHub
Functions & ModelingFree

Discriminated Unions

Model finite variants with a shared discriminant field — switch exhaustiveness, never, and type-safe handlers for API and UI state.

IntermediateFreeModeling

Discriminated unions attach a shared literal field — status, kind, or type — to each variant. Comparing that field narrows the whole object, unlocking autocomplete for variant-specific properties. This models API responses, reducer actions, and async UI state without class hierarchies.

Each variant carries only relevant fields — success has data, error has message, loading has neither. Optional-everything objects let invalid combinations type-check; tagged unions make impossible states unrepresentable at compile time.

Defining tagged variants

Generic success variants AsyncState<T> reuse the same status machine for any payload type. Consumers switch on status and get precise fields per branch without manual casts.

tagged-union.ts
Loading editor…
Outputconsole
Hello, Ada

Exhaustiveness with never

Assigning the remaining shape to never in default proves every variant is handled. Adding a new kind without a case makes default unreachable with a type error — a compile-time safety net for growing unions.

exhaustive.ts
Loading editor…

Result types and dispatch

The ok discriminant from lesson 5 is the simplest discriminated union — boolean tag with mutually exclusive payloads. Dispatch functions switch on channel or type for finite notification variants.

handlers.ts
Loading editor…
PatternDiscriminant
Async UIstatus
API resultok
Reducer actiontype

When not to use tagged unions

Open-ended JSON or plugin architectures may not fit closed variant sets — use unknown plus validation instead. For three-state booleans, a literal union on one field beats three optional booleans.

When variants grow past a dozen, consider splitting into separate types per domain area or using a registry map keyed by discriminant — long switch statements become maintenance burden even when exhaustiveness checks pass.

  • Shared literal field tags variants
  • switch narrows all branches
  • never catches missing cases
  1. 1Tag variants with a literal discriminant
  2. 2Switch for exhaustiveness
  3. 3Prefer tags over optional everything
  4. 4Next: interfaces and type aliases