Simplifying Complex TypeScript Types with the 'Unpack' Helper: Improve Developer Experience

martinpersson

Martin Persson

Posted on August 10, 2023

Simplifying Complex TypeScript Types with the 'Unpack' Helper: Improve Developer Experience

Introduction

In the world of TypeScript, developers often deal with numerous types and interfaces. Modern IDEs offer substantial assistance in understanding these complex structures, yet sometimes it's still not enough. Whether dealing with extended interfaces or nested types, reading through them can become hard. That's where the 'Unpack' helper comes into play.

The Unpack Type Helper

The Unpack type helper is designed to simplify complex TypeScript interfaces, especially those involving nested or extended interfaces. Below is the definition of the helper:

type Unpack<T> = {
  [K in keyof T]: T[K] extends object ? Unpack<T[K]> : T[K]
}
Enter fullscreen mode Exit fullscreen mode

Alternatively, you can use a shorter version, thanks to Olaoluwa Mustapha for pointing out that mapped types will return their argument as-is if it's a primitive type:

type UnpackAlt<T> = {
  [K in keyof T]: UnpackAlt<T[K]>
}
Enter fullscreen mode Exit fullscreen mode

How it Works

The Unpack type accepts a generic type parameter T, representing the complex interface you want to simplify.

By using the [K in keyof T], the helper iterates over all keys within the specified type.

The ternary condition T[K] extends object ? Unpack : T[K] checks if the current property is an object. If it is, the type helper recursively applies itself, drilling down into nested objects. If it's not an object, the property type is simply returned.

Example

Working with complex interfaces that extend other interfaces or contain nested structures can sometimes lead to a lack of clarity. Let's look at a concrete example to understand how the Unpack type helper can help.

Consider the following interfaces:

interface Base {
  _id: string
}

interface Info {
  contact: {
    email: string
  }
  socials: {
    twitter: string
  }
}

interface User extends Base, Info {
  name: string
}
Enter fullscreen mode Exit fullscreen mode

These interfaces might be common in a user management system. If you try to hover over a variable of type User, you may only see Interface User, without a clear breakdown of its structure.

Now, let's use the Unpack type helper:

type UnpackedUser = Unpack<User>
Enter fullscreen mode Exit fullscreen mode

By creating an UnpackedUser type, you can hover over it and see the fully expanded structure:

type UnpackedUser = {
    name: string;
    _id: string;
    contact: Unpack<{
        email: string;
    }>;
    socials: Unpack<{
        twitter: string;
    }>;
}
Enter fullscreen mode Exit fullscreen mode

Notice how the Unpack type helper breaks down extended and nested interfaces, providing a clear view of the structure. This enhances understanding and maintainability, offering a streamlined solution to working with complex TypeScript types.

💖 💪 🙅 🚩
martinpersson
Martin Persson

Posted on August 10, 2023

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

Sign up to receive the latest update from our blog.

Related