60

Here is an example from the official announcement about the satisfies operator :

type Colors = "red" | "green" | "blue";

// Ensure that we have exactly the keys from 'Colors'.
const favoriteColors = {
    "red": "yes",
    "green": false,
    "blue": "kinda",
    "platypus": false
//  ~~~~~~~~~~ error - "platypus" was never listed in 'Colors'.
} satisfies Record<Colors, unknown>;

What does it bring more than just:

type Colors = "red" | "green" | "blue";

// Ensure that we have exactly the keys from 'Colors'.
const favoriteColors: Record<Colors, unknown> = {
    "red": "yes",
    "green": false,
    "blue": "kinda",
    "platypus": false
//  ~~~~~~~~~~ error - "platypus" was never listed in 'Colors'.
};

In each case the platypus raises an error because the Colors type only has red, green, or blue.

1 Answer 1

79

The difference is what you can do with favoriteColors after you define it.

With satisfies, the actual type of the assigned object literal is used as the type of favoriteColors, the information about what keys and values it contains is preserved (the type of the object literal is just checked against the type it's supposed to satisfy).

// Ensure that we have exactly the keys from 'Colors'.
const favoriteColors = {
    "red": "yes",
    "green": false,
    "blue": "kinda",
} satisfies Record<Colors, unknown>;
favoriteColors.blue.toUpperCase() //ok it's a string
favoriteColors.green.toUpperCase() // error, it's a boolean 


Playground Link

Without satisfies, the type of accessing the property of favoriteColors will be unknown since the type of favoriteColors will be Record<Colors, unknown> as declared in the annotation. The information from the object literal is lost.

// Ensure that we have exactly the keys from 'Colors'.
const favoriteColors: Record<Colors, unknown> = {
    "red": "yes",
    "green": false,
    "blue": "kinda",
};

favoriteColors.blue.toUpperCase() // error, favoriteColors.blue is unknown
favoriteColors.green.toUpperCase() // error, favoriteColors.green is unknown

Playground Link

Sign up to request clarification or add additional context in comments.

4 Comments

Also, like as, it can be used in an expression, one does not need to declare a variable for it.
@Bergi This is especially useful for frameworks like Vue that use object literals a lot.
looks like an improper union to me. if you know green -> bool it's a distinct type
But unlike as, it is type-safe.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.