Annotations and Assertions 12 exercises
solution

The satisfies Operator in TypeScript

When starting on this challenge, you might have observed something interesting.

Removing the Record annotation from config led to all of the errors disappearing:

type Color =
  | string
  | {
      r: number;
      g: number;
      b: number;
    };
const config = {
  foreground: { r:
Loading solution

Transcript

00:00 You might have noticed something interesting when you started working on this. When we just remove the type annotation from config, then all of the errors actually go away below. You notice that config, without this annotation, is actually inferred as the value that's assigned to it.

00:16 So config is foreground RGB, background RGB, and border string. This means that we can access config.border.toUpperCase and we get our autocomplete back. So we actually autocomplete background, border, and foreground. Whereas without this, we actually lost all of our autocomplete on config.foreground

00:33 because the key on config could potentially be any string, which was why these tsExpectErrors were erroring, because you can access any string on this without an error. But without this annotation, then config is just inferred as the thing that's passed to it. But now we've got another issue,

00:50 because what happens if you try to actually say, OK, now background, we don't have to add the b property, even though we've specified the color up here, and this type color is actually unused. So we're now not getting any type errors on our config. We only see those later down the line.

01:07 So how would we say config needs to satisfy a certain criteria while still being inferred as what's being passed to it? Well, we can use the satisfies operator. We can say satisfies record string color.

01:23 And now, after doing this, we're going to get errors on this value. So it's like it's just checking this value, which is beautiful. And now background, we now get an error saying typeRGNumber is not assignable to type color because it's expecting property b. So property b is missing.

01:41 So let's add that in, b zero, and boom, we're back to normal. So even if we add more things to this, then it's still going to just need to satisfy record string color. So this operator is really cool because it basically means you can say, this value in this position here, doesn't matter what it is,

02:00 it has to satisfy a certain criteria, but don't let that change anything about how you infer it. This is really, really nice, and it means that config is just properly typed how we want it to be. So when you're declaring config objects like this, satisfies is a really, really nice choice.

02:19 And it's not necessarily something you should be using all of the time, but for situations like this, it's really nice. You can compare them versus variable annotations later.