TypeScript Utility Types: 9 Utility Types You Should Learn in TS

Understanding the Utility Types in TypeScript

TypeScript Utility Types represent a collection of generic types that TypeScript offers, enabling the transformation of one type into another.

They form the backbone of TypeScript’s type system and equip developers with a powerful suite of tools to shape complex type behaviors, thereby enhancing TypeScript’s adaptability and efficiency.

Let’s take a look at some of the widely used utility types:

The 9 Different Utility Types You Should Learn in TypeScript

In this section, we will be exploring the 9 different Utility Types in TypeScript that beginners should know.

1. Exclude <T, U>

The Exclude utility type in TypeScript excludes certain types from a union.

Syntax:

type Exclude = T extends U ? never : T

Here’s an illustration of how Exclude works in your code:

type T0 = Exclude<"x" | "y" | "z", "x">;
//    ^ = type T0 = "y" | "z"

type T1 = Exclude<"x" | "y" | "z", "x" | "y">;
//    ^ = type T1 = "z"

type T2 = Exclude<string | number | (() => void), Function>;
//    ^ = type T2 = string | number

In the first example, "x" is excluded from "x" | "y" | "z", leaving "y" | "z".
In the second example, "x" | "y" is excluded from "x" | "y" | "z", leaving "z".
In the third example, Function (which includes () => void) is excluded from string | number | (() => void), leaving string | number.

2.Omit <T, K>

The Omit utility type lets you create a new type by removing certain properties from an existing type.

This can be incredibly useful when you need a type that is almost identical to another type but without certain properties.

Syntax:

Omit<Type, Keys>

Here’s an illustration of how you can use it:

type YourNewType = Omit<ExistingType, 'PropertyYouWantToRemove'>;

In this example, ExistingType is the type you’re starting with, and ‘PropertyYouWantToRemove‘ is the property you want to exclude from the new type.


interface XYZ{
  x: number;
  y: number;
  z: number;
}

So, Omit is a great way to make your TypeScript code more flexible by allowing you to create new types based on existing ones, but with some properties removed. It’s a powerful tool in your TypeScript toolbox!

3. Parameters <T>

The Parameters utility type retrieves the parameter types of a function.

function greet(name: string, age: number): string {
  return `Hi, my name is ${name} and I'm ${age} years old.`;
}

type SampleParam= Parameters<typeof greet>;
//    ^ = type SampleParam= [string, number]

As you can see in our example, ‘SampleParam’ is a tuple type representing the parameter types of the ‘greet’ function, which are ‘string’ and ‘number’.

4. Partial <T>

The partial utility type in TypeScript allows you to create a new type with all properties of the original type set as optional.

It’s handy when you want to have flexibility with object properties.

For example:

// Define the Employee interface

interface Employee {
  id: number;
  name: string;
  age: number;
}


// Create an example employee
let employee: Employee = {
  id: 100101,
  name: "Coding",
  age: 18
};

// Define the Employee interface
const updateEmployee: Partial<Employee> = {
  name: "Itsourcecode"
};

// Update the employee
employee = { ...employee, ...updateEmployee };

console.log(employee);

Output:

{ id: 100101, name: 'Itsourcecode', age: 18 }

5. Pick <T, K>

The pick utility type in Typescript that allows you to create a new type by picking specific properties from an existing type.

Syntax:

type NewType = Pick<ExistingType, 'Property1' | 'Property2' | …>; 

This results in the formation of a new type (NewType), which only includes the chosen properties (Property1, Property2, etc.) from the ExistingType.

Let’s take a look at the example:

type Employee = {
  name: string;
  age: number;
  email: string;
};

Now, if you want to create a new type that only includes the ‘name’ and ’email’ properties, you can use ‘Pick’:

type EmployeeContactInfo = Pick<Employee, 'name' | 'email'>;

After that, the result of EmployeeContactInfo type will look like this:

type EmployeeContactInfo = {
  name: string;
  email: string;
}

6. Readonly <T>

The Readonly utility type in TypeScript makes all properties of a type read-only, it simply means they cannot be reassigned after creation.

For example:

interface Employee{
  id: number;
  name: string;
  age: number;
}

const employee: Readonly<Employee> = {
  id: 1011011,
  name: "Coding",
  age: 18
};

employee.id = 100001; // Error: Cannot assign to 'id' because it is a read-only property.

As expected, when we try to reassign employee.id, it results in a TypeScript error.

This is because employee is a Readonly, and its properties cannot be reassigned.

7. Record <K, T>

The Record utility type in TypeScript that is use creates a new type with specified properties and their types.

For example:

type Role = "admin" | "user" | "guest";
interface User {
  id: number;
  name: string;
}

const users: Record<Role, User> = {
  admin: { id: 101, name: "It" },
  user: { id: 1011, name: "Source" },
  guest: { id: 10111, name: "Code" }
};

In our example code, Role is a type that can be “admin”, “user”, or “guest”. User is an interface with properties id (a number) and name (a string).

The users constant is an object where each property is a Role and the value of each property is a User.

This is represented by the Record type.

So, for example, users.admin is a User with id 101 and name “It”.

8. Required <T>

The Required utility type is the opposite of Partial. It makes all optional properties in a type to be mandatory.

interface Employee {
  id?: number;
  name: string;
  age?: number;
}

const employee: Required<Employee> = {
  id: 10101,
  name: "Code",
  age: 18
};

The Required utility type does indeed make all optional properties in a type mandatory. It’s especially useful in scenarios where all fields are required, such as user registration.

In our example, the Employee interface has optional properties id and age.

When we use Required<Employee>, all properties become required. So, the employee object must have all three properties: id, name, and age.

9. ReturnType <T>

The ReturnType utility type retrieves the return type of a function.

function getEmployee() {
  return { id: 1001, name: "Code" };
}

type Employee = ReturnType<typeof getEmployee>;

const employee: Employee = {
  id: 1001,
  name: "Code"
};

In this case, it retrieves the return type of the function getEmployee, which is { id: number; name: string }.

As you can see, Employee is a type that represents the return type of getEmployee, and employee is an object of type Employee.

Conclusion

Finally, we’re done exploring all the nine (9) Utility Types that you should learn in TypeScript.

These utility types are powerful tools in TypeScript that allow you to manipulate types in various ways, making your code more flexible and maintainable.

They are especially useful in large codebases where complex type relationships are common.

I hope this article has given you some insights and helped you understand the TypeScript Utility Types.

If you have any questions or inquiries, please don’t hesitate to leave a comment below.

Leave a Comment