Skip to content

Utility Types

von Schappler edited this page Nov 27, 2024 · 1 revision

What are Utility Types?

To understand what are utility types and partials, let's assume a simple example where we have:

  • A user type defined as below
    type User = {
      id: number;
      name: string;
      password: string;
    };
  • A function to update an user, where we should be passing only the properties that should be updated, which should receive the parameters id and updateData
    const updUser = (id: number, updateData) => {
      /* update logic */
    };
  • A function to add an user, where we should be passing only required properties necessary to create an user, such as, in this case, the name and the password
const addUser = (newUser) => {
  /* add logic */
};

As we have seen before, if we try to provide just the properties we wish to change when working with object types into TypeScript, this will show us some typechecking warnings, even though the code is executed as expected.

With the knowledge we have so far, there would be thee possible ways of handling these warnings:

  1. Setting the type of the argument updateData to any (as we already discussed - this is not advised when we are going to move to production)
  2. Setting the type of the argument updateData to user (but that would require us to pass a whole user object and not only the information to be updated)
  3. Create a new type, UpdateUser with the same properties of type User, but setting all of them as opitional (this would generate bad practice, since we'd be making duplicated code when it's not necessary)

So the question is, what is the best way of solving this problem? That is where utility types and partials come into.

  • Utility types take other types as parameter and return a new type, with some changes to made to it
  • Utility types are built-in to TypéScript and allow to perform commonly-neded modifications to existing types
  • Utility types use the Generics syntax represented by a pair of angle brackets (<>)

Partial Utility type

The Partial utility type is responsible for modifying an already existing type and setting all is properties as optional.

This is basically the same as the 3rd possible way discussed above for fixing our type checking warnings, but without creating manually a new type and repating unnecessary code.

This is how it would look like on our example:

type UpdateUser = Partial<User>

const updUser = (id:number, updateData: UdpateUser) = {
  /* update logic */
}

Omit Utility type

The Omit utility type is responsible for taking an existing type AND a string (or union of strings) with a set of property names, while returning a new type with the properties declared on the type being removed from it.

This works similar to the Partial type:

const addUser = (newUser: Omit<User, 'id'>) = {
  /* add logic */
}

Note

It's part of good practices to make use of utility types declaration inline if we intend to use that specific type just once in our code.

Clone this wiki locally