Discriminated union narrowing helps TypeScript know exactly which type you are working with by checking a special property. This makes your code safer and easier to understand.
Discriminated union narrowing in Typescript
type Shape =
| { kind: 'circle'; radius: number }
| { kind: 'square'; size: number };
function area(shape: Shape) {
if (shape.kind === 'circle') {
// shape is narrowed to circle
} else if (shape.kind === 'square') {
// shape is narrowed to square
}
}The kind property is the discriminant that TypeScript uses to narrow the type.
Use simple string or number literals for the discriminant property for best results.
type is the discriminant property. Checking it narrows the type inside each branch.type Pet =
| { type: 'dog'; barkVolume: number }
| { type: 'cat'; livesLeft: number };
function describePet(pet: Pet) {
if (pet.type === 'dog') {
console.log(`Dog barks at volume ${pet.barkVolume}`);
} else {
console.log(`Cat has ${pet.livesLeft} lives left`);
}
}switch on the discriminant property status narrows the type in each case.type Response =
| { status: 'success'; data: string }
| { status: 'error'; message: string };
function handleResponse(res: Response) {
switch (res.status) {
case 'success':
console.log(`Data: ${res.data}`);
break;
case 'error':
console.log(`Error: ${res.message}`);
break;
}
}This program defines a Vehicle type with two shapes. The describeVehicle function uses the kind property to know which shape it is working with and prints details accordingly.
type Vehicle =
| { kind: 'car'; wheels: 4; brand: string }
| { kind: 'bike'; wheels: 2; hasBell: boolean };
function describeVehicle(vehicle: Vehicle) {
if (vehicle.kind === 'car') {
console.log(`Car brand: ${vehicle.brand}, wheels: ${vehicle.wheels}`);
} else if (vehicle.kind === 'bike') {
console.log(`Bike has bell: ${vehicle.hasBell}, wheels: ${vehicle.wheels}`);
}
}
const myCar: Vehicle = { kind: 'car', wheels: 4, brand: 'Toyota' };
const myBike: Vehicle = { kind: 'bike', wheels: 2, hasBell: true };
describeVehicle(myCar);
describeVehicle(myBike);Always use a common property with unique literal values for each type to enable discriminated union narrowing.
TypeScript automatically narrows the type inside the branches after checking the discriminant.
This technique helps avoid manual type assertions and makes your code safer.
Discriminated union narrowing uses a shared property to tell TypeScript which type you have.
Check the discriminant property to safely access type-specific properties.
This makes your code easier to read and less error-prone.