Annotations and Assertions 12 exercises
solution

Adding a Non-null Assertion

Inside the findUsersByName function, TypeScript is complaining about searchParams.name because it thinks we could be modifying it back to undefined inside the filter callback. This is why we were previously able to solve this problem by extracting searchParams.name into a constant variabl

Loading solution

Transcript

00:00 So the issue here, and that we've seen before, is that if you do some narrowing on searchParams.name, TypeScript thinks that when you run a function inside that scope, you could be modifying searchParams.name. You could be modifying it back to undefined. TypeScript doesn't know that kind of in this area here,

00:17 or in this scope, that we're not modifying name to be just undefined. So one way we could do this is to extract it to a constant, which we've seen before. Or we could basically tell TypeScript, and at this point here, at searchParams.name, that we're not going to modify it,

00:34 that it's never going to be null in this position. And a way that you can do that is you could basically say as string, because the issue here is that searchParams.name, it's currently typed as string or undefined. Whereas if you say as string, then fantastic, okay? Now undefined is removed, and it's only a string.

00:54 Another way you could do this, though, is you could just add a little postfix operator to it. You could add an exclamation mark there. And what this does is it basically says, okay, if there's any null or undefined inside name here, remove it. So what you could do is you could say,

01:12 name is string or null here. And so we've got string or null or undefined inside searchParams.name. And then if you add the postfix to it, a non-null assertion, then that's going to go away. So this is a really nice way that you can basically just say, okay, string or null or undefined, no, get rid of that.

01:31 Just remove the null or undefined, and I'm just left with string. You can even do this when accessing properties too. So let's imagine that searchParams itself, let's imagine that all of these parameters are optional, meaning that these objects might not exist. So here we can say searchParams is possibly undefined.

01:50 We could use a optional chaining operator to handle this, which is just a native JavaScript thing. This means that if searchParams doesn't exist, then it's not going to throw an error here, and it's just going to return undefined if not. And then though, like that might be fine, but what if we know that searchParams is there?

02:09 We can actually use the exclamation mark here. Now, this doesn't give you any safety. This is actually just a little bit funky in terms of safety. It's about as unsafe as an as. We can do the same thing on users here, and we can do the same thing on searchParams.name. So this gives you an idea of how versatile this operator is.

02:29 And also this is pretty dangerous because if we don't pass in searchParams down here, then the errors are actually going to just be, we can make it just get tons and tons of errors here. If we pass in undefined and find users by name, the tests are going to immediately fail because we're doing an unsafe property access on undefined.

02:48 So this is useful very occasionally. I would say that really it's most useful when you think you know better than TypeScript in the kind of example that we initially gave. But if you're using this too often, it's very similar to as and about as unsafe.

03:05 So I would be very careful when you're using this kind of like every other line of code or something like that. Be very, very careful with this operator because it's very easy to introduce bugs into your system.