When to Use as, satisfies, and Variable Annotations in TypeScript
Let's work through the solutions for satisfies
, as
, and variable annotations.
When to Use satifies
For the first scenario that uses a Record
, the satisfies
keyword won't work because we can't add dynamic members to an empty object.
const obj = {} satisfies Record<strin
Transcript
00:00 Okay, let's investigate this first of all we've got this object, which is an empty object as record string number Interesting what happens if we change this to be a satisfies? Well satisfies doesn't seem to work because we can't then add like dynamic members to this object
00:19 Object then gets inferred as its value here. So it's just object is an empty object So we can't add a to an empty object and we can't add B to an empty object So satisfies doesn't seem like the right one here as those seems to be working So why don't we just keep that in our back pocket and see what's going on with the rest of them? menu config down here
00:39 It's a record string label link and label with children and when we try to access members on it Then it's actually not working for us. So objects is possibly undefined That's because if we try to access menu config Then we don't get autocomplete on any of the members and so anything that we do access here
00:58 It could either be this big object or it could be undefined So that's why we can't access label on it and we can't access Children on it because children doesn't exist on both the members. So this is bloody confusing It seems like if we remove this annotation, then we're going to actually get all of our
01:19 Like this is now going to work Which is telling me that we probably need to use satisfies for this if we were to use as for this then we'd actually Get the same result as before because menu config would be inferred still as record string label link label children
01:34 So we don't want that we want to inferred as if it didn't have an annotation at all So this means we should use satisfies for this So we say satisfies removing that as and now everything's beautiful So menu config dot home dot label we get actual autocomplete on it
01:52 So home and services and children and also we can't add new stuff to it like this So this will now error because property does not exist on the thing that our config object essentially Let's look at the bottom one down here. So we know that satisfies is probably not it We've got our elements here, which is supposed to be HTML element
02:13 Now what we can do is remove satisfies then element here is still HTML element or null If we try to use a variable annotation here than HTML element And this is going to error at us because type null is not assignable to type HTML element This is kind of like we're saying to TypeScript. We know more than you do
02:34 Please don't Like don't infer the null at this point. We could use a non null assertion here, by the way That's kind of like a secret little hack But because we want to do something a little bit unsafe with TypeScript It's important to use as here and say HTML element
02:51 So now element is inferred as HTML element. We could use both of course We could say, you know HTML elements here like this, but this just seems a little bit cack-handed I'd say so as HTML element works great And this means that up here even though this is working with like object as record string number
03:11 It's just better here to say record string number And this means then that this object is properly typed and you notice by the way that we had a choice there We could either use an as or we could use a record and if you do have a choice Sorry, you can either use an as or use a variable annotation
03:28 If you do have a choice, you should always do the variable annotation because as is unsafe It is going to lead you into like dark corners because you're telling TypeScript Forcing a value to be of a certain type Whereas this object is basically just saying okay
03:45 Just annotate this variable this variable is of that certain type and then check anything that's passed to it So this is the correct way around make sure that you've got that mental model that as is used when you want to Basically tell TypeScript that you know more than it
04:01 satisfies is used when you want to basically make sure a value is checked without changing the inference on that value and then Yeah, a variable annotation is used all of the rest of the time