Production-Grade TypeScript Optional Chaining & Nullish Coalescing
Transcript from the "Optional Chaining & Nullish Coalescing" Lesson
>> The next thing we're gonna talk about is modern advancements, the latest advancements in the TypeScript language that have taken place since the TypeScript fundamentals V2 course on Frontend Masters. So what I'm gonna do here is in order to show you on my screen how all of this works, I'm just gonna create a new file in my Source folder called scratch.ts.
[00:00:29] And this is just for us to sort of goof around, and to write little code snippets. So feel free to follow along with me, but this is just for me to use this kind of like a whiteboard as we discuss these latest advancements, so this file is not that important.
[00:01:26] And then it might have an address. And I'm getting yelled at because yes, lint doesn't like that I'm failing to use this variable. Well, you can be quiet about that for this entire file. So user might have an address. In fact, let's make this even more interesting. So let's say that we have an object in here, an object that might be present.
[00:01:58] So what we can do here is to access this if we wanted to log it out. We could say x.user.address.city. And in this state, TypeScript is gonna yell at us. It's gonna yell at us because the object is possibly undefined. Right, address might be there, and it might not be there.
[00:02:28] And so we would have to make this a bit more complicated, and we might say, if the address is present, log this out. Alternatively, we can use this optional chaining. In fact, here, I can even do an optional chain. Now I'm being yelled at, cuz it's not initialized, so we can do this.
[00:02:54] Just wanna make sure the, There we go, finally made everything happy. So x, because I've done this, I'm saying I'm gonna force you to feel like you have a value for x, right? That's what this thing here is for. If we did not have this question mark, we'd have this problem, or address might not be there.
[00:03:23] And we can add this question mark here to effectively insert early termination of this expression if a null, or an undefined is encountered. So if an address is undefined, this expression will be terminated early. Now, keep in mind, this adds a condition to your code, meaning your cyclomatic complexity, if you're keeping track of that, that just went up, because you have a question mark here, right?
[00:03:57] If address is present, you do one thing. Otherwise, you do another thing. So the other thing I want you to be aware of is it's not like this whole statement will end up being terminated, right? All that happens is you're either gonna log out the city, or you'll log out undefined.
[00:04:17] We don't skip the console.log entirely. We just kinda log out. We basically evaluate to undefined if address is absent, or we get to the city if it's present, one or the other. So it's not something you wanna use just to sort of power through the potential for something to be missing, because you're still gonna get a value, and that value will be undefined.
[00:04:44] That is probably the best tip I can give you around optional chaining. So the next thing I wanna talk to you about is knowledge coalescing. The best place I found for nullish coalescing is defaults for class fields. So if I have something like this, Something like this, which, if you've taken the first course, Actually, yeah, we can do it this way.
[00:05:24] So if you've taken the first course, you know that this is a shorthand for having a class field called name, in addition to a constructor argument. So if I had a method here, I could do console/log this name, and the field is there, right? But it could possibly be undefined.
[00:05:49] So nullish coalescing would let us do something like this, name, Do this. So the double question mark is this nullish coalescing operator. And if rawName comes in as undefined or a null, we'll fall back to this default value. Now, the thing to be careful of here is if you think of this as this operator, you will run into surprises around empty strings and zeros, because those evaluate as falsi, but they are not nullish.
[00:06:53] So that's where you gotta be careful here. In TypeScript 3.8, we got class fields, which effectively is this. So this hashtag at the beginning of a field name gives us something called hard privacy. So this is different than simply the underscore, or simply having the word private. So if you've ever consumed, if you've ever written a library in TypeScript and use private, you know that if somebody sets a break point, they can still see name.
[00:07:33] It's still there. And particularly, if someone's consuming this code, and they don't use the type information, there is no indication that this is private. Now, if we have this hashtag at the beginning of the field name, it's it's actually private. If you set a breakpoint, and have an instance of foo, and you try to access this at runtime, it won't be there anymore.
[00:07:55] So this is true privacy, meaning only this class can have access to this. It's also useful because you can override it in subclasses safely. So if I had another class extending from foo, it could have its own hashtag name. It doesn't know thing about the fact that the base class has a hashtag name.
[00:08:15] It's private data, and it doesn't inherit because it's private. We also got namespace exports, which is just this syntax here, export star as foo from some module like this. Now, this is useful. We'll use it later as we sort of define a public API surface. This is great if you wanna make a library with a single entry point, and you have a bunch of other modules.