TypeScript
What is a discriminated union?
Learn tagged unions.
What is a discriminated union?
A discriminated union is a union where every member has a common property (the discriminant) and that property takes a different literal value in each member. Thanks to the common field, TypeScript can narrow the union to a single member with a check. This enables processing complex data models safely.
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; size: number };
function area(s: Shape): number {
if (s.kind === "circle") {
return Math.PI * s.radius ** 2; // circle
}
return s.size ** 2; // square
}
Discriminant field
The discriminant field is typically named kind, type, or tag. Each member gives this field its own unique literal value; for example "circle", "square". When a check tests this literal value, TypeScript narrows the union to that member.
type Action =
| { type: "add"; item: string }
| { type: "remove"; id: number };
function run(a: Action) {
if (a.type === "add") {
a.item; // string
} else {
a.id; // number
}
}
Exercise Shape area with a discriminated union
Define the Shape discriminated union type: "circle" (radius: number) and "square" (size: number) members, with a kind discriminant field. Write an area(s: Shape): number function. If s.kind === "circle", return Math.PI * s.radius ** 2; otherwise return s.size ** 2. Print results via console.log(area({ kind: "circle", radius: 2 })) and console.log(area({ kind: "square", size: 3 })).
Show example solution
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; size: number };
function area(s: Shape): number {
if (s.kind === "circle") {
return Math.PI * s.radius ** 2;
}
return s.size ** 2;
}
console.log(area({ kind: "circle", radius: 2 }));
console.log(area({ kind: "square", size: 3 }));
Test yourself
-
What is required for a union to be discriminated?
- All members have the same shape
- At least one property is optional
- Every member is a class
- A common property takes a different literal value in each member
Show answer
A common property takes a different literal value in each member — A discriminated union requires a common discriminant field that takes a different literal value in each member; this lets TypeScript narrow the union to a single member with a check.
-
Discriminant field
type Shape =
| { kind: "circle"; radius: number }
| { kind: ____; size: number };
function area(s: Shape) {
if (s.kind === "square") return s.size ** 2;
return Math.PI * s.radius ** 2;
}
Show answer
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; size: number };
function area(s: Shape) {
if (s.kind === "square") return s.size ** 2;
return Math.PI * s.radius ** 2;
}
-
Discriminated union parts
- Discriminant alanı
- different literal value in each member
- Ortak özellik
- present in all members
- Narrowing
- done via discriminant check
- Union
- combination of member types
Next lesson: Literal discriminant