Best ways to use "Extract" utility type in Typescript
Tags: typescript, webdev, tutorial, beginners
Published: 2023-04-12 16:30:51

`Extract` is a utitly type in `Typescript` that allows you to create a new type by extracting a subset of an existing type.

**_This article is inspired from [this](https://www.totaltypescript.com/uses-for-exclude-type-helper) article from `Matt Pocock`._**

> Here are few possible ways to use `Extract` in `Typescript`:

## Table of contents

- [Get a member of an union](#get-a-member-of-an-union)
- [Get multiple members from an union](#get-multiple-members-from-an-union)
- [Get a member of a discriminated union](#get-a-member-of-a-discriminated-union)
- [Get multiple members of a discriminated union](#get-multiple-members-of-a-discriminated-union)
- [Get members of a discriminated union by shape](#get-members-of-a-discriminated-union-by-shape)
- [Get members by a type](#get-members-by-a-type)
- [Get strings containing a substring from an union](#get-strings-containing-a-substring-from-an-union)
- [Get strings with one of several possible values from an union](#get-strings-with-one-of-several-possible-values-from-an-union)
- [Conclusion](#conclusion)

## Get a member of an union
We can extract a member of `union` by using `Extract`. The first argument is the full union, and the second argument is the member of the union that we want to get.

```ts
type Animal = "cat" | "dog" | "bird" | "fish";

type OnlyCat = Extract<Animal, "cat">; // 'cat'
```
---

## Get multiple members from an union
We can even get mulitple members from an union by using `Extract`. Here is how:

```ts
type Animal = "cat" | "dog" | "bird" | "fish";

type ExtractType = Extract<Animal, "cat" | "dog">; // 'cat' | 'dog
```
Even if we pass a value to `Extract` that doesn't exist in the union, Typescript will return the values that exists in the union.

```ts
type Animal = "cat" | "dog" | "bird" | "fish";

type ExtractType = Extract<Animal, "cat" | "dog" | "tiger">; // 'cat' | 'dog'
```
---

## Get a member of a discriminated union

```ts
type Shape =
  | {
      type: 'square'
    }
  | {
      type: 'circle'
    }
  | {
      type: 'triangle'
    }
```
A discriminated union type is one where each member has a discriminant property. The discriminant property is a common property that can be used to discriminate between the other members. In the example above, the `type` property is used to discriminate between the different shapes.

We can extract a member of the discriminated union by using `Extract` like this:

```ts
type SqaureShape = Extract<Shape, {type: 'square'}> // { type: 'square' }
```
---

## Get multiple members of a discriminated union
We can also extract multiple members of a discriminated union:
```ts
type SqaureAndCircleShape = Extract<Shape, {type: 'square'} | {type: 'circle'}> 
// { type: 'square' } | { type: 'circle' }
```
This works even if the union members have other properties attached to them.

```ts
type Shape =
  | {
      type: 'square';
      size: number;
    }
  | {
      type: 'circle'
    }
  | {
      type: 'triangle'
    }

type SqaureAndCircleShape = Extract<Shape, {type: 'square'} | {type: 'circle'}> 
// {type: 'square'; size: number;} | { type: 'circle' }
```
You can also get multiple members of the discriminated union by passing a `union` to the `type` property:

```ts
type Shape =
  | {
      type: 'square';
      size: number;
    }
  | {
      type: 'circle'
    }
  | {
      type: 'triangle'
    }

type SqaureAndCircleShape = Extract<Shape, {type: 'square' | 'circle'}> 
// {type: 'square'; size: number;} | { type: 'circle' }
```
---

## Get members of a discriminated union by shape

```ts
type Routes =
  | {
      route: '/user'
      search: {
        id: string
      }
    }
  | {
      route: '/user/create'
    }
  | {
      route: '/user/edit'
      search: {
        id: string
      }
    }

type RoutesWithSearch = Extract<
  Routes,
  {
    search: any
  }
>
/* 
{
    route: '/user';
    search: {
        id: string;
    };
} | {
    route: '/user/edit';
    search: {
        id: string;
    };
}
*/
```
To get the members of union you don't need to always include the `discriminator` (in this case, `route`) in the second argument. You can just pass the `shape` of the members you want to get.

In this case, we want to extract the types from the Routes union type that have a search property.

---

## Get members by a type

```ts
type allTypes = 'admin' | 'user' | 5 | 6 | 7 | true

type onlyNumbers = Extract<allTypes, number> // 5 | 6 | 7
```
In the example above, we remove all literals that don't match the number type from the `allTypes` union. Hence, we are only getting the numbers.

---

## Get strings containing a substring from an union

```ts
type keys = 'userId' | 'tweetId' | 'userName' | 'tweetName'

type UserKey = Extract<keys, `${'user'}${string}`> // "userId" | "userName"
```
The resulting `UserKey` type will be a union of the string literals from strings that start with the string "user." This case will include only the `userId` and `userName` string literals.

---

## Get strings with one of several possible values from an union

```ts
type keys = 'userId' | 'tweetId' | 'id' | 'userName' | 'friendName'

type OnlyIdKey = Extract<keys, `${string}${'id' | 'Id'}${string}`> 
// "userId" | "tweetId" | "id"
```
You can also use `Extract` to get all strings from a union that contain one of several possible substrings.

In this case, the resulting `OnlyIdKey` type will be a `union` of the string literals from `keys` containing the `id` or `Id`. This case will include the `userId`, `tweetId`, and `id` string literals.

---
---

## Conclusion
So that's it, guys. I hope you found the article helpful. `Extract` is a utility type that can be used in many ways. If you think there are more ways to use `Extract,` please let me know in the comments. Thanks for reading the article. I will see you all in my next article🐸.

**Visit:**
👨‍💻[My Portfolio](https://portfolio-khaki-iota-89.vercel.app/)
🏞️[My Fiverr](https://www.fiverr.com/sunnyislam990)