| ▲ | RHSeeger 8 hours ago | |
This was a fantastic writeup, thanks. If you don't mind an additional question... How does this work,
Since- person isn't const, so person.isCool could be mutated - coolPeopleOnly requires that it's input mean not only Person, but isCool = true. | ||
| ▲ | MrJohz 2 hours ago | parent [-] | |
If you ignore the `satisfies` for a moment, the type of `person` is the literal object type that you've written (so in this case, { "person": string, isCool: true }). So coolPeopleOnly(person) works, regardless of whether `satisfies` is there, because TypeScript sees an object literal that has all the person attributes and also `isCool: true`. (You could mutate it to `isCool: false` later, but then TypeScript would complain because `isCool: false` is different to `isCool: true`. When that happens isn't always obvious, TypeScript uses a bunch of heuristics to decide when to narrow a type down to the literal value (e.g. `true` or `"Jerred"`), vs when to keep it as the more general type (e.g. `boolean` or `string`).) What `satisfies` is doing here is adding an extra note to the compiler that says "don't change the type of `person` at all, keep it how it is, _but_ also raise an error if that type doesn't match this other type". (This is only partially true, I believe `satisfies` does affect the heuristics I mentioned above, in that Typescript treats it a little bit like `as const` and narrows types down to their smallest value. But I forget the details of exactly how that works.) So the `coolPeopleOnly` check will pass because the `person` literal has all the right attributes, but also we'll get an error on the literal itself if we forget an attribute that's necessary for the `Person` type. | ||