TypeScript: From First Steps to Professional

Type Narrowing, Guards, & Aliases

Anjana Vakil
Software Engineer & Educator
TypeScript: From First Steps to Professional

Lesson Description

The "Type Narrowing, Guards, & Aliases" Lesson is part of the full, TypeScript: From First Steps to Professional course featured in this preview video. Here's what you'd learn in this lesson:

Anjana discusses union types, where a type can encompass multiple values. She demonstrates how to narrow down union types to avoid errors, such as calling properties on undefined values. Anjana also introduces type guards to handle different narrower types within union types and explains the use of type aliases to simplify type annotations and reuse type definitions.

Preview
Close

Transcript from the "Type Narrowing, Guards, & Aliases" Lesson

[00:00:00]
>> Anjana Vakil: With union types, what we have here is a type that I said was wider or encompasses more values than our primitive types number or string The union type number or string is wider than the type number and the type string So we talk in TypeScript about types being wider or narrower than each other So for example, a literal string is narrower than the primitive type string, which is so wide it encompasses every possible string you could ever possibly write

[00:00:43]
And so when we're working with union types, sometimes we need to narrow down which exact side of the union this value might be, so that we don't do things like call properties that don't exist on undefined, like we had before So for example, let's say I have a variable that is either going to be an HTML element or null Like for example, the kind of thing that I might get back if I ask to pull an element by its ID out of the HTML in the DOM

[00:01:30]
I don't know if this ID might exist I don't know if it actually is in the page somewhere as an ID on an actual HTML element So this might return null, or it might return an element And so if we try to do something like add an event listener to this value, which may or may not be an HTML element, JavaScript would just be like, oh, you tried to call a method on undefined, cannot read properties, no

[00:02:06]
But TypeScript will help us out Just going to put this in the So here because the type of this elm or null might be null, TypeScript is like, hey now, you probably didn't mean to do this because you said that elm or null could be null, and now you're acting as though it definitely has this method add event listener, and that is not true

[00:02:45]
So don't forget your elm or null is possibly null So what we do to make sure that we're not doing things like trying to read properties of null is we can put what are sometimes referred to as type guards in place, which often looks like an if statement, or sometimes a ternary if or things like that And what happens is we want to handle these two different narrower types differently

[00:03:29]
So if the value is null, and here I have a type guard, this is sort of like guarding against the case where elm or null is null, then we're not going to try to add an event listener, we're going to do something else And then in the else statement, we can do the event listener and not get an error because now TypeScript knows, because it read our code and it knows that we are now in the branch of this if where we've already eliminated or narrowed down the set of possible values for elm or null to only be an HTML element because that's the only non-null option

[00:04:15]
And so there we don't get the squiggle because HTML elements do have the add event listener method So this is something that we saw earlier with how we had to handle that optional property We had to make sure we were handling the case where it might be undefined And what this term of type narrowing refers to within each of these branches, the value of our variable is narrower than the original wider type

[00:04:56]
So in the if, we know that elm or null is in fact null, because that's what the if says And in the other branch, we know that it's the other thing OK And so we've already been doing this, but as you can see, we have all these building blocks, numbers and strings and arrays and blah blah, and we're going to need to customize our code to create whatever the particular types are that we need because one size does not fit all

[00:05:31]
Thank you, Heidi And so now we're getting into a fun new keyword that only exists in TypeScript syntax where we can start naming these types so that we don't lose our minds writing really long type annotations So for example, if I want to keep reusing this string or number thing without having to type string, pipe, number over and over again, I can create what's called a type alias with this keyword type

[00:06:11]
And it kind of looks like a variable, but convention is that we give it capital, sometimes called Pascal case, so capital like class type names And then we have an equal sign, but this is just assigning the type There's no value yet This is just a type And then we can have whatever we want on the right hand side This could be our parenthesis, string or number array or blah blah

[00:06:40]
So for example, here we have another type alias called log level This is now the name of a type that is the union of three literals So here's another example of where literal types might be useful is when you know that there's only so many different possible values this can be And similarly, we can create aliases for object types with this exact same syntax

[00:07:07]
And again, this looks very similar to actually giving JavaScript an object, but what we've got here is, again, our syntax for property type, property type, property optional type And now, once we have these aliases, we can hover over them, cool, but we can also say, let's say const user, oh sorry, lowercase user one is ID one, username one

[00:07:52]
And if we want to make sure that it's not something else, blurp 5, that's not something we want, we can give this variable a type named user And what is that type It's the type that we defined here with this type, name of type, equals shape of type And so now once we've typed this variable, TypeScript knows that there is no such thing as a blurb on a user

[00:08:33]
And it also knows that, yeah, there's a full name, but 4 is not a good value for it And so we don't have to keep writing this whole thing every time, that would be really rough So we can use type aliases to make our lives easier, the same way that we use variables in JavaScript, we can use type aliases, sort of like variables for types

[00:08:58]
There's recursive where you could define a type and then link another type You can have recursive types, yes, but out of scope for this course, but that's another one of the many ways that you can type it, if you can dream it Where there's a will, there's a type.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now