TypeScript - Record and the satisfies
operator
This post is part of an ongoing series on TypeScript. In it, I try to explain in a detailed way different situations I’ve faced while building relatively big React applications using TypeScript, and moving them from JavaScript. Here’s a list of other posts I’ve written about TypeScript:
In a previous entry I argued that the use of the Record
type is dangerous in some circumstances and suggested using a Dictionary
type to solve that. The goal of the Dictionary
type is to make sure the type of values from property access returns T | undefined
as opposed to just T
(which would suggest that we have a T
for any K
in the dictionary).
The release of TypeScript 4.9 includes a new operator called satisfies
. It can be used to solve the situation I presented in that other post:
type Breed = string
interface Dog {
name: string
}
const dogsByBreed: Record<Breed, Dog[]> = {
akita: [{ name: 'Walter' }, { name: 'Gracie' }],
dachshund: [{ name: 'Charlie' }],
}
dogsByBreed.poodle // Type is Dog[], value is undefined.
Instead of introducing a Dictionary
type, you can now simply do this:
const dogsByBreed = {
akita: [{ name: 'Walter' }, { name: 'Gracie' }],
dachshund: [{ name: 'Charlie' }],
} satisfies Record<Breed, Dog[]>
dogsByBreed.poodle // Type error!
TypeScript gives us a static type-check with the message:
Property 'poodle' does not exist on type '{ akita: { name: string; }[]; dachshund: { name: string; }[]; }'.
Which is absolutely correct and gives us the best of both worlds:
- We made sure that
dogsByBreed
satisfies ourRecord<Breed, Dog[]>
constraint. - We lost no type information at all about the
dogsByBreed
variable, and TypeScript was able to tell us thatpoodle
is not one of its keys.
I’m happy to be able to update the previous post to link to this one. Until next time!