Introducing the Satisfies Operator in TypeScript 4.9

23 December 2022
#react#typescript#satisfies

The typescript 4.9 announced a new operator - satisfies (you can check it on official blog post)

Motivation

The goal of this operator is to ensure that some expression matches some type, but also want to keep the most specific type of that expression for inference purposes.

Let's say we want to have common color type and it can be a string or an RGB tuple:

type Color = string | { r: number; g: number; b: number };

const redColor = 'red' as Color;
// Errors:
// Property 'toUpperCase' does not exist on type 'Color'.
// Property 'toUpperCase' does not exist on type '{ r: number; g: number; b: number; }'
console.log(redColor.toUpperCase());

as Color can't automatically understand whether normalizedRedColor is a string or an object. We can't do operations with a string (toUpperCase()) or with an object (get property from object color.r).

We can do it just if we write as follows:

console.log(typeof redColor === 'string' && redColor.toUpperCase());

But it's hard to check the const type every time.

Example

The new satisfies operator lets us validate that the type of an expression matches some type and validate that all the properties of color are compatible with a string or an object:

type Color = string | { r: number; g: number; b: number }; // type can be whether a string or an object

const stringColor = 'red' satisfies Color;
console.log(stringColor.toUpperCase()); // valid operation as stringColor is a string

const rgbColor = { r: 0, g: 0, b: 0 } satisfies Color;
console.log(rgbColor.r, rgbColor.b, rgbColor.g); // valid operation as stringColor is an object

const palette = {
  red: { r: 255, g: 0, b: 0 },
  black: 'black',
  white: { r: 255, g: 255, b: 255 },
  // Error
  // Object literal may only specify known properties, and 'c' does not exist in type '{ r: number; g: number; b: number; }'
  aqua: {r: 0, g: 255, c: 255}
} satisfies Record<string, Color>;
console.log(palette.red, palette.black, palette.white); // valid operation as palette is a string record of Color

As you can see satisfies determined the correct type automatically and we don't need to do extra stuff. Also it can catch typo errors if it's not matched with the type.