Type predicates are used to determine if a given value belongs to a certain type or not, providing a hint to the TypeScript compiler about the type information.

## What are Type Predicates ๐คโ

In TypeScript, discriminated unions (also known as tagged unions or algebraic data types) are a powerful feature that allows you to create and work with complex types in a type-safe and expressive manner. They are particularly useful for modeling state transitions and handling different cases in a structured way.

A discriminated union is a union type (a type that can be one of several types) where a common property, called the discriminant or tag, is used to determine which specific type within the union is being represented. Each type in the union has a unique value for the discriminant property, enabling TypeScript to distinguish between them and provide appropriate type checking and code completion.

Here's an example illustrating the concept of discriminated unions in TypeScript:

`// Define a common "kind" property as the discriminant`

interface Circle {

kind: "circle";

radius: number;

}

interface Square {

kind: "square";

sideLength: number;

}

interface Rectangle {

kind: "rectangle";

width: number;

height: number;

}

// Create a discriminated union type

type Shape = Circle | Square | Rectangle;

// Function to calculate the area of a given shape

function getArea(shape: Shape): number {

switch (shape.kind) {

case "circle":

return Math.PI * shape.radius * shape.radius;

case "square":

return shape.sideLength * shape.sideLength;

case "rectangle":

return shape.width * shape.height;

default:

// Exhaustiveness checking

const _: never = shape;

return _;

}

}

In this example, `Shape`

is a discriminated union type consisting
of `Circle`

, `Square`

, and `Rectangle`

. The `kind`

property acts as the
discriminant. The `getArea`

function uses a switch statement to determine the
correct formula for calculating the area of a given shape, and TypeScript
ensures that all cases are properly handled, providing compile-time type
checking and error detection.

# Time To Transition From JavaScript To TypeScript

Level Up Your TypeScript And Object Oriented Programming Skills. The only complete TypeScript course on the marketplace you building TypeScript apps like a PRO.

SEE COURSE DETAILS## How is it Helpful ๐คโ

Discriminated unions in TypeScript are helpful and different from normal switch case statements or conditional statements in JavaScript in several ways and the most prominent of them all is exhaustiveness checking.

TypeScript can help you ensure that all possible cases of a discriminated union are handled in a switch statement. If a new case is added to the union type, TypeScript will raise a compilation error if the switch statement doesn't handle the new case. This can help you catch potential bugs early on during development.

### Example of Exhaustiveness Checking With Discriminated Unions ๐คโ

In the example below, I have added a new interface called `Triangle`

and
included it in the `Shape`

discriminated union type. The `getArea`

function,
however, has not been updated to handle the new `Triangle`

case. As a result,
the TypeScript compiler will raise an error due to the exhaustiveness checking
provided by the discriminated unions.

`// Define a common "kind" property as the discriminant`

interface Circle {

kind: "circle";

radius: number;

}

interface Square {

kind: "square";

sideLength: number;

}

interface Rectangle {

kind: "rectangle";

width: number;

height: number;

}

// Adding a new interface called Triangle

interface Triangle {

kind: "triangle";

base: number;

height: number;

}

// Updating the discriminated union type to include the new Triangle interface

type Shape = Circle | Square | Rectangle | Triangle;

// Function to calculate the area of a given shape

function getArea(shape: Shape): number {

switch (shape.kind) {

case "circle":

return Math.PI * shape.radius * shape.radius;

case "square":

return shape.sideLength * shape.sideLength;

case "rectangle":

return shape.width * shape.height;

// The new "triangle" case is missing, causing a compilation error

default:

// Exhaustiveness checking

const _: never = shape;

return _;

}

}

In this example, the TypeScript compiler will raise an error due to the
missing "triangle" case in the `getArea`

function's switch statement, enforcing
exhaustiveness checking. To fix the error, you would need to add a case to
handle the `Triangle`

type:

`/** ...`

case "triangle":

return (shape.base * shape.height) / 2;

**/

## What Can You Do Next ๐๐โ

If you liked the article, consider subscribing to Cloudaffle, my YouTube Channel, where I keep posting in-depth tutorials and all edutainment stuff for ssoftware developers.