Satisfies

Loading "Satisfies"
πŸ‘¨β€πŸ’Ό Ok, so repeating ourselves there is not awesome. The problem is that we want to enforce the value of our operations object, but to do that we either have to widen the type of our key or list it explicitly as we're doing. This is because when you cast your object to a type, TypeScript widens your type as far as that cast. Here's a simple example of the problem:
type ValidCandies = 'twix' | 'snickers' | 'm&ms'
const candy: ValidCandies = 'twix'
// candy is 'twix' | 'snickers' | 'm&ms'
What we need is some way to enforce the values of our object, without having to annotate our object. We can do this using TypeScript's satisfies syntax. For example:
type ValidCandies = 'twix' | 'snickers' | 'm&ms'
const candy = 'twix' satisfies ValidCandies
// candy is 'twix'
See? No type widening! Wahoo!
Before satisfies came out, we had to use a "Constrained Identity Function" (pattern coined by yours truly). Learn more in How to write a Constrained Identity Function (CIF) in TypeScript

Please set the playground first

Loading "Satisfies"
Loading "Satisfies"