Skip to content

The Awesome satisfies Operator in TypeScript

Posted on:July 15, 2023

If you haven’t read first article on the topic, please check it out: Understanding the satisfies Operator in TypeScript

Table of contents

Open Table of contents

Understanding the satisfies Operator

The satisfies operator allows you to match a type to an actual expression for inference purposes. Let’s dive into an example to see its practical application.

Consider an interface for a product.

interface Product {
  name: string;
  price: number;
  category: string;
}

Now, imagine a scenario where you have a userSelection that could be either a string or a product. You might be tempted to use an intersection type like this.

type UserSelection = string | Product;

However, this approach can lead to issues when trying to access properties specific to either a string or a Product.

The Problem with Intersection Types

Here’s a common mistake using intersection types.

// Bad Example
const badUserSelection: UserSelection = {
  id: 1,
  itemName: "Laptop",
  itemPrice: 1200,
};

In this example, the compiler cannot determine the type of itemName and itemPrice accurately. As a result, when trying to access properties, it might lead to errors, especially if the type is ambiguous.

Enter the satisfies Operator

Now, let’s see how the satisfies operator can help.

// Good Example
const goodUserSelection = {
  id: 1,
  itemName: "Laptop",
  itemPrice: 1200,
} satisfies UserSelection;

By using satisfies, we explicitly state that the provided object satisfies the UserSelection type. This helps TypeScript infer the type correctly, providing accurate autocompletion and type-checking support.

No More Enums

The satisfies operator also proves useful when dealing with enums. Let’s consider the case of number-based enums.

The Problem with Number-Based Enums

// Bad Example
enum BadStatus {
  Available,
  OutOfStock,
}

function updateStatus(status: BadStatus) {
  // ...
}

In this scenario, updateStatus can accept any number, leading to potential runtime errors.

A Better Approach Instead of relying on number-based enums, consider using a type or a string-based enum.

// Good Example
type GoodStatus = "Available" | "OutOfStock";

function updateStatus(status: GoodStatus) {
  // ...
}

By using a type or a string-based enum, you ensure that only valid statuses can be passed to the function, making your code more reliable and less error-prone.

Conclusion

The satisfies operator in TypeScript is a valuable addition that can significantly improve the type inference process. By using it wisely, you can enhance the reliability of your code and make your development experience more enjoyable. Embrace this operator, avoid common mistakes, and write TypeScript code that is not only robust but also a pleasure to work with. Happy coding!