Reputation: 747
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
.
Upvotes: 54
Views: 21951
Reputation: 249556
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
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
Upvotes: 70