TypeScript Tutorial · Generics and Type Manipulation · Lesson 20 of 25
TypeScript Discriminated Unions
Model states safely with a shared literal tag.
A union with a tag
Give each member of a union a common literal property (the discriminant, often kind, type or status). Checking it narrows to exactly one member:
type Event =
| { type: "click"; x: number; y: number }
| { type: "keypress"; key: string }
| { type: "scroll"; offset: number };
function describe(e: Event): string {
switch (e.type) {
case "click":
return `click at ${e.x},${e.y}`;
case "keypress":
return `key ${e.key}`;
case "scroll":
return `scrolled to ${e.offset}`;
}
}
const events: Event[] = [{ type: "click", x: 10, y: 20 }, { type: "keypress", key: "Enter" }, { type: "scroll", offset: 300 }];
events.forEach((e) => console.log(describe(e)));
Output
click at 10,20 key Enter scrolled to 300
Modelling state
Discriminated unions make impossible states impossible — a request can't have both data and error:
type RequestState<T> =
| { status: "idle" }
| { status: "loading" }
| { status: "success"; data: T }
| { status: "error"; error: string };
function render(state: RequestState<string[]>): string {
if (state.status === "success") return `Loaded ${state.data.length} items`;
if (state.status === "error") return `Error: ${state.error}`;
return state.status === "loading" ? "Loading..." : "Press load";
}
console.log(render({ status: "idle" }));
console.log(render({ status: "loading" }));
console.log(render({ status: "success", data: ["a", "b"] }));
console.log(render({ status: "error", error: "Network down" }));
Output
Press load Loading... Loaded 2 items Error: Network down
The Result type is a popular pattern for errors without exceptions — try the Result type problem.
Test yourself
What makes a union 'discriminated'?
Using the | operatorA shared literal property that identifies each memberUsing classesHaving exactly two members
Show answer
Answer: A shared literal property that identifies each member
Practice next
- Result Type Instead of Exceptions · coding problem