Better Code Quality with TypeScript’s Utility Types: Pick, Partial, and Omit

martinpersson

Martin Persson

Posted on August 14, 2023

Better Code Quality with TypeScript’s Utility Types: Pick, Partial, and Omit

Introduction

I see a lot of projects that don't use TypeScript's type helpers like Pick, Partial, and Omit. These are very powerful tools that can create new interfaces, making your code cleaner and easier to reason about. In many cases, developers tend to avoid using these helpers due to unfamiliarity or the perceived complexity, but they can greatly enhance code quality.

The Problem

Let's say we have a large User interface that's being used across the app in various functions. And because we use it in so many places, we have to make the properties optional to fit various use cases. This, however, leads to a lack of clarity about what is truly required in different contexts, making the code more prone to errors and harder to understand. For example:

interface User {
  id?: number
  name?: string
  email?: string
  password?:string
  phone?: string
}
Enter fullscreen mode Exit fullscreen mode

And we have some functions that use the User interface like so:

function updateUser(user: User) {
  // ...
}

function sendEmailNotification(user: User) {
  // ...
}

function logUserDetails(user: User) {
  // ...
}
Enter fullscreen mode Exit fullscreen mode

This approach may seem convenient, but it has some significant drawbacks:

  • Lack of Precision: Using the entire User interface in each function means that all properties are considered optional, even when certain properties are required for a specific function. For instance, the updateUser function might need the id, but by marking it as optional, you risk runtime errors if it's not provided.

  • Poor Maintainability: Any change to the User interface could inadvertently affect all functions, creating a fragile codebase. For example, if you add a property to the User interface, you'll need to ensure that it doesn't disrupt the existing functions, leading to increased complexity and a higher chance of mistakes.

  • **No Flexibility: **The broad use of the User interface across functions prevents you from enforcing specific constraints where needed. For example, the sendEmailNotification function might only need the name and email, but the lack of constraints means that developers could accidentally pass in unnecessary or incorrect data, leading to bugs or security concerns.

  • Overhead and Confusion: By using a general interface everywhere, it becomes harder for developers to understand what each function expects and returns. This not only slows down the development process but also makes code reviews and debugging more challenging, as the intended behavior is obscured.

By addressing these issues with more specific types like Partial, Pick, and Omit, you can create a codebase that is more robust, maintainable, and clear.

Solutions

These three TypeScript helpers allow you to create more specific and efficient types based on existing ones.

Partial

Partial<Type> makes all properties of Type optional. It's useful when you want to work with subsets of an object.

When updating a user, you might not need to provide all the fields. Here's how Partial can be used:

function updateUser(user: Partial<User>) {
  // Update only the provided fields of the user
  // ...
}
Enter fullscreen mode Exit fullscreen mode

Here we can pass the properties we want to update, and we don't need to update the whole user.

Pick

Pick<Type, Keys> creates a new type by picking a set of properties Keys from Type.

When notifying a user via email, you might only need the name and email fields. Here's how Pick can help:

function sendEmailNotification(user: Pick<User, 'name' | 'email'>) {
  // Send an email to the user using the name and email
  // ...
}
Enter fullscreen mode Exit fullscreen mode

Omit

Omit<Type, Keys> creates a new type by omitting a set of properties Keys from Type.

For logging user details without sensitive information like email and password, you can use Omit:

function logUserDetails(user: Omit<User, 'email' | 'password'>) {
  // Log details without exposing sensitive information
  // ...
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

By using TypeScript's utility types like Partial, Pick, and Omit, you can create more precise, maintainable, and flexible code. This not only improves the developer experience but also leads to a safer and more robust application. If you've been avoiding these tools, give them a try in your next project. You might be surprised at how much they can enhance your coding style!

💖 💪 🙅 🚩
martinpersson
Martin Persson

Posted on August 14, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related