A Discriminated union in TypeScript is used to discriminate between union types by having a property that holds a literal type as its value to help us identify the type of object we are working with.
Let us look at an example, to understand this concept better.
interface Developer {
type: "developer";
language: string;
}
interface DBA {
type: "dba";
database: string;
}
type Employee = Developer | DBA;
function getInfo(employee: Employee) {
switch (employee.type) {
case "developer":
console.log(`Programming language to use: ${employee.language}`);
break;
case "dba":
console.log(`Database to use: ${employee.database}`);
}
}
let developer: Developer = {
type: "developer",
language: "Javascript",
};
let dba: DBA = {
type: "dba",
database: "MySQL",
};
getInfo(developer); // Programming language to use: Javascript
getInfo(dba); // Database to use: MySQL
In the above example, we have an interface Developer
interface Developer {
type: "developer";
language: string;
}
Here, we have a field type
that discriminates this interface from others by specifying its value as developer
. We can use this field to identify if an object belongs to the interface Developer
whenever it is necessary to do so.
Similarly, we have another interface DBA
that also has a type but the value is dba
interface DBA {
type: "dba";
database: string;
}
Next, we create a type Employee
which is a union of Developer
and DBA
.
type Employee = Developer | DBA;
We have also created a function called getInfo()
, which takes the object of type Employee
as its parameter. This means the value passed to getInfo()
can only be determined at runtime.
This creates an issue for TypeScript because the parameter passed can either be type Developer
or DBA
. Let’s say we pass an object of type Developer
and in our function, we try to access the property database
.
From the definition of Developer
interface, we know that database
property cannot be accessed by the object of type Developer
. Hence, we need a way to differentiate object that is of type Developer
from type DBA
. This is where discriminated unions come into the picture.
function getInfo(employee: Employee) {
switch (employee.type) {
case "developer":
console.log(`Programming language to use: ${employee.language}`);
break;
case "dba":
console.log(`Database to use: ${employee.database}`);
}
}
With the help of the discriminated union, we can simply check if employee.type === "developer"
or if employee.type === "dba"
. This way we can prevent the code from breaking.