top | item 46018575

(no title)

ptrl600 | 3 months ago

This is wordier than just "as const", what advantage does it give? (I am a newbie and genuinely don't know)

edit: perhaps the advantage only comes into play for mutable values, where you want a narrower type than default, but not that narrow. Indeed, this is covered in the article, but CTRL+F "as const" doesn't work on the page for whatever reason, so I missed it.

discuss

order

reissbaker|3 months ago

The satisfies keyword is quite different than "as const." What it does is:

1. Enforce that a value adheres to a specific type

2. But, doesn't cause the value to be cast to that type.

For example, if you have a Rect type like:

    type Rect = { w: number, h: number }
You might want to enforce that some value satisfies Rect properties... But also allow it to have others. For example:

    const a = { x: 0, y: 0, w: 5, h: 5 };
If you wrote it as:

    const a: Rect = // ...
TypeScript wouldn't allow you to also give it x and y properties. And if you did:

    as Rect
at the end of the line, TypeScript would allow the x, y properties, but would immediately lose track of them and not allow you to use them later, because you cast it to the Rect type which lacks those properties. You could write an extra utility type:

    type Location = { x: number, y: number };
    const a: Location & Rect = // ...
But that can get quite verbose as you add more fields. And besides: in this example, all we actually are trying to enforce is that the object is a Rect — why do we also have to enforce other things at the same time? Usually TS allows type inference for fields, but here, as soon as you start trying to enforce one kind of shape, suddenly type inference breaks for every other field.

The satisfies keyword does what you want in this case: it enforces the object conforms to the type, without casting it to the type.

    const a = { x: 0, y: 0, w: 5, h: 5 } satisfies Rect;
    // a.x works
Then if someone edits the code to:

    const a = { x: 0, y: 0, width: 5, height: 5 } satisfies Rect;
TypeScript will throw an error, since it no longer satisfies the Rect type (which wants h and w, not height and width).

RHSeeger|3 months ago

This was a fantastic writeup, thanks. If you don't mind an additional question...

How does this work,

    function coolPeopleOnly(person: Person & { isCool: true }) {
        // only cool people can enter here
    }

    const person = {
        name: "Jerred",
       isCool: true,
    } satisfies Person;

    coolPeopleOnly(person);
Since

- person isn't const, so person.isCool could be mutated

- coolPeopleOnly requires that it's input mean not only Person, but isCool = true.

nixpulvis|3 months ago

Why is satisfies needed at all, when can't. Typescript realize that `a` satisfies `Rect` automatically?

michaelcampbell|3 months ago

Thanks; succinct and for me, I understood it.

bastawhiz|3 months ago

I've really only found benefit on the return type of functions, when you can say that a type parameter satisfies a type (with the return type being a boolean). This let's you use `if (isPerson(foo))` and typescript will narrow the type appropriately in the conditional

iddan|3 months ago

With as const you can’t verify against another interface