5 Useful TypeScript Utility Types

5 Useful TypeScript Utility Types

Typescript has a flexible type system that allows users to create new types. Additionally, with the help of utility types, developers can transform existing types.

In this article, we review five useful TypeScript utility types.

Awaited<Type>

Awaited is created to model await in async functions or the .then() method in promises.

type T1 = Awaited<Promise<number>>;
// Type T1 = number

type T2 = Awaited<Promise<Promise<string>>>;
// type T2 = string

type T3 = Awaited<boolean | string | Promise<number>>;
// type T3 = boolean | string | number

NonNullable<Type>

NonNullable creates a new type by excluding null and undefined from the Type.

type T0 = string | number | null | undefined;

type T1 = NonNullable<T0>;
// type T1 = string | number

Exclude<UnionType, ExcludedMembers>

Exclude constructs a new type by excluding ExcludedMembers from UnionType.

type T0 = Exclude<"a" | "b" | "c" | "d", "a" | "d">
// type T0 = "b" | "C"

You can use Exclude to filter undesirable types such as null and undefined from a type. In this case, Exclude has the same effect as NonNullable.

type T1 = string | number | null | undefined;

type T2 = Exclude<T1, null | undefined>
// type T2 = string | number

Extract<Type, Union>

Extract constructs a new type by extracting Union from Type. You can view Extract as opposite of Exclude.

type T1 = Extract<"x"|"y"|"z", "y">  
// type T1 = "y"

type T1 = Extract<"x"|"y"|"z", "y" | "z">
// type T2 = "y" | "z"

Extract can be thought of as the intersection of two given types. In the following example, common elements of two types are extracted.

type T3 = Extract<'a' | 'b' | 'c', 'a' | 'b' | 'd'>; 
// type T3 = 'a' | 'b'

One useful use case of Extract is to find the common base of two types.

interface Human {
  id: string;
  name: string;
  surname: string;
  ssn: number;
}

interface Dog {
  id: string;
  name: string;
  breed: string;
  sound: string;
}

type CommonKeys = Extract<keyof Human, keyof Dog>;
// type CommonKeys = "id" | "name"

Record<Keys, Type>

Record creates a new type whose property keys are Keys and whose property values are Type. You can use this utility to map the properties of a type to another type.

type Coordinates = Record<"x"|"y"|"z", number>
// Type Coordinates = { x: number, y:number, z: number}
interface PageInfo = { 
  id: number;
  route: string;
  title: string;
};

type PageName = 'home' | 'services' | 'about' | 'contact';

const pages: Record<PageName, PageInfo> = {
 home : {id: 1, route: "home", title: "Home"},
 services : {id: 2, route: "services", title: "Services"},
 about : {id: 3, route: "services", title: "Services"},
 contact : {id: 4, route: "services", title: "Services"},
}

Summary

Awaited, NonNullable, Extract, Exclude and Record are TypeScript utility types that help developers to create new types by transforming existing ones.