Recently, I came across a pattern named Discriminated Unions Types in TypeScript. In this blog post, let us learn about that.
Discriminated Unions are a pattern where each type in the union has a common property.
In TypeScript, a union type allows a variable to hold one of several specified types. A straightforward example of a union type could be the union of string and number types
type StringOrNumber = string | number;
function printValue(value: StringOrNumber) {
if (typeof value === "string") {
console.log("String value:", value.toUpperCase());
} else {
console.log("Number value:", value.toFixed(2));
}
}
printValue("Hello"); // HELLO
printValue(42); // 42.00
The union type StringOrNumber can hold either a string or a number. This type ensures that the printValue function can accept arguments of either type while maintaining type safety.
You can create a union-type Animal from Bird and Fish, as shown below.
type Fish = { swim: () => void };
type Bird = { fly: () => void };
type Animal = Fish | Bird;
function handleAnimal(animal: Fish | Bird) {
if ("swim" in animal) {
console.log("It's a fish!");
} else {
console.log("It's a bird!");
}
}
You understand the type of union now, so let’s return to the pattern of Discriminated Unions.
Discriminated unions are patterns in which each type has a common property that distinguishes it from the others. This makes narrowing easier.
To convert the above union type Animal as Discriminated Unions, we need to add a common property to each type in the union. This property will help distinguish between the types of Fish and Bird, and allow TypeScript to narrow the type based on its value.
type Fish = { type: "fish"; swim: () => void };
type Bird = { type: "bird"; fly: () => void };
type Animal = Fish | Bird;
After that, amend the handleAnimal function to check the type property to determine whether it is a Fish or a Bird.
function handleAnimal(animal: Animal) {
if (animal.type === "fish") {
console.log("It's a fish!");
animal.swim();
} else if (animal.type === "bird") {
console.log("It's a bird!");
animal.fly();
}
}
The Fish and Bird objects must each include a type property to use a discriminated union type Animal.
const fish: Fish = {
type: "fish",
swim: () => console.log("Fish is swimming"),
};
const bird: Bird = {
type: "bird",
fly: () => console.log("Bird is flying"),
};
handleAnimal(fish);
handleAnimal(bird);
You should use Discriminated Unions for better type safety and maintainability of TypeScript code.
Discover more from Dhananjay Kumar
Subscribe to get the latest posts sent to your email.