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
dogsByBreedsatisfies ourRecord<Breed, Dog[]>constraint. - We lost no type information at all about the
dogsByBreedvariable, and TypeScript was able to tell us thatpoodleis not one of its keys.
I’m happy to be able to update the previous post to link to this one. Until next time!