Advanced Props 12 exercises

Comparing `as const`, `as`, and `satisfies`

Let's start by fixing the error where buttonProps was being inferred as a string which is not assignable to button, submit, or reset.

A First Attempt with as const

As we've seen before, using as const will allow us to infer this properly.

const buttonProps = {

Loading solution


00:00 Okay, let's take a look. The first thing I want to take a look at is actually this button prop type down the bottom here. This is being inferred as string. We know that we can change that by making this an as const, because as const here actually freezes this type of button, and it means that we can actually infer this properly.

00:18 This actually means here that button props now works because the error that was happening was because this button, the type of the property type is incompatible. Type string, which is what it was being inferred as, is not assignable to button or submit or reset. So what we kind of want to do here

00:37 is we can just add as const, then that error goes away, and this means that this is being inferred as button, but we're not getting any kind of erroring or even any autocomplete inside these button props. So what you kind of want to do, or what like my first instinct would be, is actually to remove the as const

00:57 and type this as component props button, because what this is going to do is it's going to actually make this button props, the component props of a button. It means that inside here, we're going to get all of the autocomplete that we want in order to actually make these props work, and this illegal property is going to error

01:15 because illegal property does not exist on button props, but this means actually the button prop type here, it's actually being inferred as all of the possible types of that button. And you can actually go inside here and like access things that aren't even on this button props that we've actually declared here.

01:35 So this is like less of a good solution. Another way you could potentially think to do it is you could actually do using as here, and you could say as component props button. Let's just try this briefly. And what's going on here now is, let me just add this semicolon to the end. You might think, okay, this is working fine,

01:53 but actually there's no error here because as actually does a transformation. It doesn't really like validate the thing that's on the button props. And this illegal property is actually allowed to pass into the as without being checked. So as is kind of like the most cheaty,

02:11 cheeky way of possibly assigning this property. And it lets you do kind of illegal things here. So I'm going to ditch as completely. But what if there was a way that we could ensure that button props sort of satisfies a contract without actually overriding it and forcing it to be that contract?

02:30 Well, we can use satisfies. Now satisfies, what it's doing is it's making sure that button props validates this type. So illegal property is erroring here, and it's going to give us autocomplete on all of these elements. But it's also going to not override the type itself. This means that button props

02:48 is actually just what we've specified here. And you notice that because it's clever enough to understand that type button can only be of those elements, we actually can't pass in anything illegal up here, not assignable to type button or submit or reset or undefined. It's actually properly inferring the type there without us needing to use as const.

03:07 So this is the solution here. Satisfies shouldn't be necessarily your default, but it's really great in situations where you just want to make sure that button props is of a certain type, but you don't want to allow access to things that might not be defined on there. And it's really, really smart for doing a lot of this kind of thing.

03:25 And I wanted to cover it just to give you some clarity over where it sits in comparison to this sort of normal annotation operator

03:33 and as, and also with as const too.