Check out a free preview of the full Making TypeScript Stick course:
The "Checked index access" Lesson is part of the full, Making TypeScript Stick course featured in this preview video. Here's what you'd learn in this lesson:

Mike discusses the compiler flag that automatically describes the possibility of being undefined: noUncheckedIndexAccess.

Get Unlimited Access Now

Transcript from the "Checked index access" Lesson

>> The final TypeScript language feature that I think is of the most important ones to people writing everyday TypeScript code is another great one, checked index access. So if you've taken my TypeScript Fundamentals course, you may have heard me go on rant about dictionaries, and arrays, and how if we typed dictionaries like this, we're being way too optimistic.

[00:00:27] So you can see here, we're saying, I have a collection where I store string arrays under keys. Great, so let's create an empty dictionary. And then what the type system seems to think is completely okay is I'm just gonna pass in a key that I know doesn't exist in this data structure.

[00:00:47] And it's letting me go ahead and act as if there's a string array that I get back. There's no sense of the dictionary might not have a value for me, right? There's no sense of is there something present? Let's make sure we check first. So what you may have seen me suggest that you do is something like this down here, where you always add this undefined.

[00:01:13] In your types, you be honest, and you describe that the possibility exists for there to be nothing under some subset of keys. In fact, the vast majority of keys hold nothing, the vast majority of possible strings in the universe, right? And so here we get an appropriate type error, right?

[00:01:39] There is no rhubarb in this empty dictionary here. So we're told, look, you should probably check this out first. Just give me a truthy, falsy check. We could do this. We could handle it very gracefully here. We'd just have to do const { rhubarb } = d, and then if (rhubarb), we just need to use a type guard, and then we can narrow that down.

[00:02:10] So we'd just have to do something like this, which is absolutely the right thing to do when we're not sure whether something's there. So here you can see the possibility for something to be undefined exists. And down here, it does not, because of the type guard. So what we get here, and unfortunately, I cannot show it to you in these little code snippets, because we do not have the technology yet to turn this compiler flag on for some examples, and not for others.

[00:02:42] You get a compiler flag that says noUncheckedIndexAccess. And here's what that means. If I click this link down here, So here, I do have this compiler flag turned on. Let me make sure I'm not lying, no. There it is, noUncheckedIndexAccess, great. So now we can see that when I get rhubarb back, there is the possibility that it's undefined, even though I have not explicitly said so up here.

[00:03:15] So this will be the case for arrays, and for dictionaries, or objects. Anywhere you have an index signature, there is an assumption that there might be nothing here. If we look at an example of how this is applied, we have a compiler option turned on here. It's called noUcheckedIndexAccess.

[00:03:37] There it is. It's checked off. That means it's enabled. And even though we have not up here explicitly said T or undefined, we are getting an equivalent result here. We can see that when we grab the value stored under a particular key, object is possibly undefined. And this encourages us to use some sort of guard, or optional chaining, depending on what you're doing, in order to address that possibility, rather than running smack into the error of cannot call function join on undefined, which will happen at runtime.

[00:04:15] The whole point is to avoid that kind of thing. That's why we use TypeScript, right? Now, there is a little bit of a downside to this, and that would be dealing with arrays. So when we're using higher order functions on arrays or dictionaries, if you use something like Lodash, you might be used to doing something like this.

[00:04:44] Oops, sorry. So we could do that, and then, We get a value out, see string or undefined. Great, this has been fixed. So now, because in this situation, right, when we're looping over this array, there is some checking that happens behind the scenes, right? We're not trying to access a value at a particular key, we're saying for every value that is found, invoke this callback.

[00:05:27] That's what I'm gonna use to transform things. So actually, I see no downside here anymore. But it used to be that this value was string or undefined, and this would require that you either filter the array beforehand, or do some checking within this little callback. But now, all of the higher order functions that you would expect to be invoked on a per member basis, you will already have that undefinedness kind of worked out of the type, and this should behave as usual.

[00:05:56] Great, I love finding surprise lack of downsides.