11 Awesome TypeScript Utility Types You Should Know
Tags: javascript, typescript, tutorial, beginners
Published: 2020-12-21 13:17:35

*This post was originally published at [kais.blog](https://kais.blog/p/11-awesome-typescript-utility-types-you-should-know).*

**Let's move your learning forward together!** [Follow me on Twitter](https://twitter.com/intent/follow?screen_name=kais_blog) for your daily dose of developer tips. Thanks for reading my content!

---

My last two posts have already shown you [14 Awesome JavaScript Array Tips You Should Know About](https://dev.to/kais_blog/14-awesome-javascript-array-tips-you-should-know-about-1d0m) and [10 Awesome JavaScript String Tips You Might Not Know About](https://dev.to/kais_blog/10-awesome-javascript-string-tips-you-might-not-know-about-4ep2). However, I usually write code in TypeScript. There's also much to learn. So today, I'd like to show you 11 awesome TypeScript utility types. With these, constructing new types becomes a breeze.

- [Pick\<Type, Keys>](#picklttype-keysgt)
- [Omit\<Type, Keys>](#omitlttype-keysgt)
- [Readonly\<Type>](#readonlylttypegt)
- [Partial\<Type>](#partiallttypegt)
- [Required\<Type>](#requiredlttypegt)
- [Record\<Keys, Type>](#recordltkeys-typegt)
- [Parameters\<Type>](#parameterslttypegt)
- [ReturnType\<Type>](#returntypelttypegt)
- [Extract\<Type, Union>](#extractlttype-uniongt)
- [Exclude\<Type, ExcludedUnion>](#excludelttype-excludeduniongt)
- [NonNullable\<Type>](#nonnullablelttypegt)

You don't have to do anything special. All utility types are globally available by default.

# Pick\<Type, Keys>

With `Pick` you can pick a set of `Keys` from the given `Type`. The example shows a `signup` function taking a `user` as first parameter. The parameter type is constructed by picking the `email` and `password` property from the `User` type. This way, you won't need to pass an `id` for signing up a new user.

```ts
interface User {
  id: string;
  email: string;
  password: string;
}

function signup(user: Pick<User, "email" | "password">): User {
  //
}

signup({
  email: "kai@example.com",
  password: "secret",
});
```

# Omit\<Type, Keys>

In contrast to `Pick`, you can use `Omit` to remove a set of `Keys` from your `Type`. The example is similar to the previous. In this case, the `signup` function's parameter `user` has all properties from the `User` type minus the `id` property.

```ts
interface User {
  id: string;
  email: string;
  password: string;
}

function signup(user: Omit<User, "id">): User {
  //
}

signup({
  email: "kai@example.com",
  password: "secret",
});
```

# Readonly\<Type>

Sometimes you want to prevent that an object's properties are reassigned. This is doable with the `Readonly` utility type. The constructed type will have all properties set to read-only. Thus, you can't reassign any property of that type. In the following example, we'll create a new type by using `Readonly` and the `User` type. We can't reassign the `password` property here, because it's read-only now.


```ts
interface User {
  id: string;
  email: string;
  password: string;
}

const user: Readonly<User> = {
  id: "d70989c8-c135-4825-a18c-a62ddf9ae1d5",
  email: "kai@example.com",
  password: "secret",
};

user.password = "correcthorsebatterystaple";

// ERROR: Cannot assign to 'password' because it is a read-only property.
```

# Partial\<Type>

Using `Partial` you can construct a type with all properties from `Type` set to optional. For example, the `updateUser` function allows you to update a `User`. The second parameter expects the fields to update. You can use `Partial` with the `User` type here, so that `fields` is any combination of fields from the `User` type.

```ts
interface User {
  id: string;
  email: string;
  password: string;
}

function updateUser(user: User, fields: Partial<User>): User {
  //
}

const user: User = {
  id: "d70989c8-c135-4825-a18c-a62ddf9ae1d5",
  email: "kai@example.com",
  password: "secret",
};

updateUser(user, { password: "correcthorsebatterystaple" });
```

# Required\<Type>

`Required` is the opposite of `Partial`. You can use it to construct a type with all properties from `Type` set to required. The following example has a `User` type with an optional `avatar` property. However, our variable `userWithAvatar` requires all properties to be present. Thus, an error occurs.

```ts
interface User {
  id: string;
  email: string;
  password: string;
  avatar?: string;
}

const userWithAvatar: Required<User> = {
  id: "d70989c8-c135-4825-a18c-a62ddf9ae1d5",
  email: "kai@example.com",
  password: "secret",
};

// ERROR: Property 'avatar' is missing in type '{ id: string; email: string; password: string; }' but required in type 'Required<User>'.
```

# Record\<Keys, Type>

With the `Record` utility type, you can easily construct a new type with `Keys` as keys and `Type` as values. In this example, each `User` has a role. We want to describe an object that groups `userA` and `userB` by their respective role. Using `Record`, we can tell the TypeScript compiler that the object has a `string`s as keys and an array of `User`s as values. Besides, to be more explicit, we could have used `User["role"]` instead of `string` for the keys. 

```ts
interface User {
  id: string;
  email: string;
  password: string;
  role: string;
}

const userA: User = {
  id: "d70989c8-c135-4825-a18c-a62ddf9ae1d5",
  email: "kai@example.com",
  password: "secret",
  role: "administrator",
};

const userB: User = {
  id: "c0e26c7e-9787-4d56-81b4-4440759e251c",
  email: "katharina@example.com",
  password: "correcthorsebatterystaple",
  role: "moderator",
};

const usersGroupedByRole: Record<string, User[]> = {
  administrator: [userA],
  moderator: [userB],
};
```

# Parameters\<Type>

Use `Parameters` to extract a function's parameters. This will construct a tuple type with the parameters. Let's say you'd like to initialize a variable that holds parameters for a `signup` function. With the help of `Parameters` you can extract the `signup` function's parameters and create a tuple type. Then, you can use the `parameters` whenever you want. 

```ts
interface User {
  id: string;
  email: string;
  password: string;
}

function signup(email: string, password: string): User {
  //
}

type SignupParameters = Parameters<typeof signup>;
//                    = [email: string, password: string]

const parameters: SignupParameters = ["kai@example.com", "secret"];

signup(...parameters);
```

# ReturnType\<Type>

The utility type `ReturnType` helps by extracting the return type of a function. Look at the following example. We want our `ValidationResult` type to be constructed by looking at the return type of the `validate` function. Here, it's pretty simple. You could have used `boolean` directly instead. However, sometimes it's nice to be able to extract a function's return type.

```ts
interface User {
  id: string;
  email: string;
  password: string;
}

function validate(user: User): boolean {
  //
}

type ValidationResult = ReturnType<typeof validate>;
//                    = boolean
```

# Extract\<Type, Union>

Sometimes, you'd like to extract types from an union of types. For that, you can use the `Extract` utility type. Every union member from `Type` that is assignable to the `Union` is kept.  In the following examples, we'll have unions of strings. There, we extract a part of it for our types `TypeA` and `TypeB`. For `TypeC` we extract each union member that is assignable to `Function`.

```ts
type TypeA = Extract<"apple" | "banana" | "cherry", "apple">;
//         = "apple"

type TypeB = Extract<"apple" | "banana" | "cherry", "apple" | "banana">;
//         = "apple" | "banana"

type TypeC = Extract<string | (() => string), Function>;
//         = () => string
```

# Exclude\<Type, ExcludedUnion>

The `Exclude` utility type is the opposite of the `Extract` utility type. This time, it removes all union members from `Type` that are assignable to the `ExcludedUnion`. Similar to the previous examples, we have unions of strings here. In contrast to last time, we are removing union members instead of keeping them.

```ts
type TypeA = Exclude<"apple" | "banana" | "cherry", "apple">;
//         = "banana" | "cherry"

type TypeB = Exclude<"apple" | "banana" | "cherry", "apple" | "banana">;
//         = "cherry"

type TypeC = Exclude<string | (() => string), Function>;
//         = string
```

# NonNullable\<Type>

`NonNullable` works similar to the `Exclude` utility type. It excludes `null` and `undefined` from the given `Type`. Similar to the previous two examples, we construct the new types `TypeA` and `TypeB` by removing union members from a given `Type`. Here, `null` and/or `undefined` are removed.

```ts
type TypeA = NonNullable<"apple" | null>;
//         = "apple"

type TypeB = NonNullable<"apple" | null | undefined>;
//         = "apple"
```

# Conclusion

This was a quick overview of some of the most useful utility types. They can be used for a wide range of things. I use them in almost every project. However, there are more utility types. Check out the [official documentation](https://www.typescriptlang.org/docs/handbook/utility-types.html) to learn more! Besides, you can find even more such types. For example, the [`type-fest`](https://github.com/sindresorhus/type-fest) package adds many essential types to your project.

Thanks a lot for reading this post. Please consider sharing it with your friends and colleagues. See you soon!

---

**Let's move your learning forward together!** [Follow me on Twitter](https://twitter.com/intent/follow?screen_name=kais_blog) for your daily dose of developer tips. Thanks for reading my content!

*This post was originally published at [kais.blog](https://kais.blog/p/11-awesome-typescript-utility-types-you-should-know).*