Understanding Conditional Types in TypeScript
Tags: webdev, javascript, programming, beginners
Published: 2022-11-17 11:59:23

---
title: Understanding Conditional Types in TypeScript
published: true
date: 2022-11-16 11:00:56 UTC
tags: webdev, javaScript, programming, beginners
canonical_url: https://www.syncfusion.com/blogs/post/understanding-conditional-types-in-typescript.aspx
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/abzu2ywnfsx1dra2lbqh.png
---

Conditional types allow developers to use conditions when introducing their types. It is a bit of an advanced feature in TypeScript, and many developers do not use it in day-to-day work. But knowing these features can certainly help you to write better code. In this blog, I will introduce you to conditional types in TypeScript.

## What Are Conditional Types?

Conditional types are non-uniform type mappings. In other words, they are type transformations that differ depending on a condition. Let’s take a look at a code snippet.

```js
interface Animal {
}
interface Dog extends Animal {
}
 
type Ex1 = Dog extends Animal ? number : string; //type of Ex1 = number

type Ex2 = RegExp extends Animal ? number : string; // type of Ex2 = string
```

Here, types **Ex1** and **Ex2** are decided by the condition of whether they are extending the type **Animal** or not. As the type **Dog** is extending the **Animal** type, the condition evaluates as true, and the **Ex1** type is evaluated to the type number. For **Ex2** , since the **RegExp** type is not extending the **Animal** type, the condition evaluates as false. Therefore, the **Ex2** type is evaluated to the type string.

## Why Do We Need Conditional Types?

As mentioned, conditional types are similar to the ternary operator, which we’ve all used in JavaScript. Conditional types allow developers to decide the type of a certain variable or the method’s return type based on a condition.

However, using conditions and types together might confuse you if you haven’t used them before. Therefore, let me help you understand conditional types with a simple example. First, let’s take a look at this simple function.

```js
function createLabel(label) {
   return label && label.replace(/\s/g, "_");
}
```

Here, the **createLabel** method takes a text label as an input parameter. The **createLabel()** function returns **null** if the label value equals **null.** If not, it replaces all the white spaces in the label with underscores and returns the label. Although this function looks straightforward with no issues, TypeScript may throw an error saying that the value could be null.

For example, if you invoke the **createLabel()** function with **createLabel(“foo and poo”).toUpperCase()**, it will throw an error since TypeScript is unable to comprehend the type of input.

To avoid this, we can use overloaded functions.

```js
function createLabel(label:string): string;
function createLabel(label:null): null;
function createLabel(label: string | null): string | null;
```

Here, the function overloads resolve the previously discussed issue. But these function overloads introduce a new set of problems. For example, if they’re used in a library, having to sort among these function overloads every time this function is called can be cumbersome and would decrease the library’s performance. On the other hand, if the requirement changes and we need to add another variable to the same function, the number of function overloads we need to write will grow exponentially.

So, we need another solution for this issue, and that’s where the conditional types come into play.

## How Conditional Types Work

With conditional types, the **createLabel()** function will look like the following.

```js
function createLabel<T extends string | null>(label: T): T extends string ? string : null {
    return (label ? label.replace(/\s/g, "_") : null) as any;
}
```

**Note:** Here, I have cast the function’s return value as **any.** This is an open issue in TypeScript, and the only way to get the benefit of using conditional operators is to cast the return this way.

In the previous function, I introduced a new syntax for the types, which works similarly to the ternary operator. If the condition is true, it will take the first type; if not, it will take the second type. This implementation avoids the previous problems we had with the function overloads, as it can evaluate the type in the runtime.

In conditional types, the most important syntax is the **extends** keyword, as it decides which type of condition should finally be evaluated. Therefore, understanding how the **extends** keyword works will help in better understanding the conditional types.

Let’s focus on understanding the **extends** keyword.

### extends keyword

Take a look at the following example of a conditional type.

```js
A extends B ? A : B
```

This condition will be true if A extends B. This means that the value of type A should be assignable to a variable in type B. Therefore, the **extends** keyword is actually checking whether A is assignable to type B. Based on this condition, the conditional type will decide which type it should finally evaluate.

Other than being capable of evaluating the type based on a condition, conditional types have a few other exciting features that make them more attractive.

## Features of Conditional Types in TypeScript

### Inferring with Conditional Types

Condition types can handle ambiguities with the help of the **infer** keyword. We can use the **infer** keyword after the **extends** keyword to infer types from the true conditional branch.

Let’s take a look at the following example.

```js
type Box<T> = T extends Array<infer A> ? A : never;
 
type Books = Box<string[]> // type string
```

In this example, the type of Books is a string, since the generic is a string array. If we change the generic to **any** type, which is not an array, the type of Books will be **never.** Conditional types are capable of gracefully handling such ambiguities in types.

### Distributive conditional types

Another feature of conditional types is their distribution capability when a union type is given while working with generics. This might sound confusing, so let’s look at an example.

```js
type Apple = {};
type Banana = {};
type Orange = {}
 
type Fruits = Apple | Banana | Orange;
 
type Box<T> = T extends any ? T[] : never;
 
type FruitBox = Box<Fruits>; //Apple[] | Banana[] | Orange[]

```

Conditional types can identify the underlying types of the union, and the conditional type be applied to each member of the union recursively.

```js
type FruitBox = Box<Apple> | Box<Banana> | Box<Orange>
```
Then, it will apply the conditional type to each type separately.

```js
type FruitBox = Apple[] | Banana [] | Orange[];
```

## Conclusion

Conditional types might not be a feature used in daily work. But it is a very powerful feature that TypeScript introduced to handle types with conditions dynamically. Using conditional types when implementing libraries and handling APIs can help developers improve their code base.

I hope you have found this article helpful and thank you for reading it!

Syncfusion’s [Essential JS 2](https://www.syncfusion.com/javascript-ui-controls "Syncfusion Essential JS 2 UI controls") is the only suite you will ever need to build an app. It contains over 65 high-performance, lightweight, modular, and responsive UI components in a single package. Download a [free trial](https://www.syncfusion.com/downloads/essential-js2 "Free evaluation of the Syncfusion Essential Studio") to evaluate the controls today.

If you have any questions or comments, you can contact us through our [support forums](https://www.syncfusion.com/forums "Syncfusion Support Forum"), [support portal](https://support.syncfusion.com/ "Syncfusion Support Portal"), or [feedback portal](https://www.syncfusion.com/feedback/ "Syncfusion Feedback Portal"). We are always happy to assist you!

## Related blogs

- [JavaScript Debugging with VS Code and Chrome](https://www.syncfusion.com/blogs/post/javascript-debugging-with-vs-code-and-chrome.aspx "Blog: JavaScript Debugging with VS Code and Chrome")
- [JavaScript String Manipulation Techniques Every Developer Should Know](https://www.syncfusion.com/blogs/post/javascript-string-manipulation-techniques-every-developer-should-know.aspx "Blog: JavaScript String Manipulation Techniques Every Developer Should Know")
- [JavaScript API Mocking Techniques](https://www.syncfusion.com/blogs/post/javascript-api-mocking-techniques.aspx "Blog: JavaScript API Mocking Techniques")
- [JavaScript Map vs. Object](https://www.syncfusion.com/blogs/post/javascript-map-vs-object.aspx "Blog: JavaScript Map vs. Object")