455

May 9th, 2022 × #TypeScript#JavaScript#Web Development

TypeScript Fundamentals × Narrowing, Discriminating Unions, and Type Guards

An episode discussing TypeScript fundamentals like type narrowing, discriminated unions, and strategies for type guards.

or
Topic 0 00:00

Transcript

Scott Tolinski

Welcome to Syntax.

Scott Tolinski

On this Monday, hasty treat, it. We are going to be talking about some TypeScript fundamentals.

Topic 1 00:30

Talking TypeScript fundamentals

Scott Tolinski

We're gonna be talking about what is called type narrowing, it. Discriminating unions and type guards. Basically, we're gonna be helping you solve some of those errors that pop up in your TypeScript code That make you very frustrated because you say, hey. This thing is supposed to be this thing. Why is it giving me an error? My name is Scott Talinski. I'm a developer from Denver, Colorado, and with me, as always, is Wes Boss.

Wes Bos

Can you narrow what's that from? Is that Simpsons?

Topic 2 01:01

Narrowing types in TypeScript

Scott Tolinski

I don't know. I've never heard that Can't collection of words in that melody. Canyon arrow. There's, like, a Oh, Canyon arrow. Yes. Oh. Yeah.

Scott Tolinski

Yeah. That kinda, it kind of says Simpsons to me.

Wes Bos

Oh, that's a good one. Simpsons, I don't Do very many Simpsons jokes, but that one came out

Scott Tolinski

came out of left field. It it did. Might he have a left field. What didn't come out of left field, Wes, is our 2 sponsors today, which is Sentry and Payments Hub. So Sentry is the perfect place to see all of your errors and exceptions and mark them as done. Attach them to releases. Attach some to GitHub issues or, even just users. You can create an issue directly from something that is an issue, an exception in your code. You can assign it to a user right then and there, and more importantly, you can see all of the things that you might want to know to solve that issue. For it. For instance, right, maybe what operating system? What browser? Oh, like, you can see that this is this is coming in from an Internet Explorer on an old Windows computer. You might say, you know what? It. I don't need to solve this issue. I don't I feel like I I don't need to solve this issue because this is gonna be more trouble than it's worth. Either way, Sentry is the perfect a place to keep track of everything that's going on in your application and make sure it's working its very best. So head on over to century.i0.

Topic 3 02:20

Sentry sponsor

Scott Tolinski

Use the coupon code

Wes Bos

treat all lowercase, all one word, and you'll get 2 months free. Thank you so much for Century for being such a great sponsor. We also we got a brand new Sponsor on. So hold on and listen to this. Payments Hub is a new sponsor of us, and they do some really cool stuff Around easy to use APIs and SDKs that you can integrate into your application. And this is not Just you throw it on your website and you sell something.

Wes Bos

They offer a full fleet of APIs that allow you to Integrated into some software. You can integrate it into a point of sale system. So, like, if you are building something That allows your your product to go ahead. Like you built a product and your product is used by people who then need to onboard other people. You need to underwrite them.

Wes Bos

You have merchants in there. You have to process their payments. They provide data analytics via the API. They do all kinds of stuff. And, like, This seems like I don't want to say the the Swiss army knife, but, like, this seems like the API set That you need if you need to be able to do some very complex stuff with your payment integration, like from very low level All the way through to to accept the payments. It looks awesome.

Wes Bos

They also have they've sent us over some stuff that I'm just really excited about having this sponsor on myself because this seems really, really neat. Their code samples and everything looks pretty slick.

Wes Bos

They have Some, ad read here that I'll I'll rattle through for you as well.

Topic 4 04:00

PaymentsHub sponsor

Wes Bos

Their dev portal gives you easy to use APIs and SDKs that allow developers to create Ecommerce websites develop in person point of sale applications and launch full featured omnichannel payment solutions. Our API rich product landscape is ideal interested in programmatic merchant onboarding and access accessing payment transaction data Through an API looks really sweet. So you want to check it out at developer.paymentshub.comforward/syntax.

Wes Bos

They have a really neat landing page that allows you just to quickly go through. They also have like a really they have like lots of products. And on the products page, it will tell you which ones are PCI compliant and which ones aren't and like which one you have to specifically choose If you need to be following different, different compliance, which is very much appreciated because I've gone down that rabbit hole before. Check it out. Developer.paymentshub.comforward/syntax.

Scott Tolinski

Yeah. And and give that landing page a check too, like you just mentioned, because It's always nice when these companies, they give us a little landing page just for, our listeners to yeah. Just to say, here's here's what's up. You know, here's here's what's going on. And, I think, payments have did a great job here. So, yeah, thank you for payments up for being a new sponsor. Yeah. Welcome. Alright. So let's get into

Wes Bos

TypeScript fundamentals. We've done a couple TypeScript fundamentals episode, it. And I was just going through all of the notes and and planning for my TypeScript course, and I was going through, Sort of the area that you hit type narrowing and creating type guards on set. Like, I don't think we've actually ever talked about this on, on the podcast before. So We're going to dive into explaining.

Topic 5 05:44

What is type narrowing?

Wes Bos

I think this is one of those things that sounds scarier than it is. What do you think about that? I was about to say that.

Wes Bos

So it's like, oh, discriminating unions, type guards, type narrowing. Oh, that Sounds complicated, and it kind of just boils down to, in TypeScript. You got to check that you got the right type before you go ahead and use it. It. There is no assuming in TypeScript, I think, is the, the way that I would like to put it. And TypeScript will yell at you if you try to Assume that the data or the type coming in is what you assume it is,

Scott Tolinski

and TypeScript will make a pass out of you.

Wes Bos

Exhaustively check it.

Wes Bos

So should we well, should we, like, start off with explaining what type narrowing is? Yeah. So type narrowing is basically,

Scott Tolinski

you you're thinking about When things are defined as types, it's not always clear cut whether this thing is a string, a number, or whatever. Sometimes it's multiple things.

Topic 6 06:35

Using type guards

Scott Tolinski

And then as you go, you might want to be using specific properties on one thing that don't exist on another thing. So let's say you had it. A variable that was a number or a string.

Scott Tolinski

Type narrowing is basically where you're saying, alright. I want to use a string method on this thing that doesn't exist in a number method or a method on a number type. So, therefore, I need to narrow the type down to be a string, so to say, so that we're not gonna get an error saying you cannot use 2 lowercase on property of number or whatever that ends up being.

Scott Tolinski

It. The most common error that you do see associated with this is argument type of this or this or this or this is not assignable to parameter type of this. It. Type blank is not assignable to type blank. Yeah.

Scott Tolinski

It it's like what? It's probably the most common error that you see in TypeScript script when you you're getting going with it. You're working it. You're you're feeling very comfortable TypeScript, and then all of a sudden you say, how is this possible? I feel like I've done everything in my power to say that this is a string, and,

Wes Bos

that's not always the case. And we're gonna talk a little bit about some strategies here. Yeah. Another example I have here that's coming from my upcoming course is that you've got a function that takes in a food, And that food could either be a type like they like a food is kind of the generic type. And then we extend the generic food type and we create a sandwich and we create a pizza. Right.

Wes Bos

And if you have a function that takes in either a sandwich or pizza, and in that function, there might be, like, toast.

Wes Bos

Right? You don't wanna well, maybe you want would want to, but you don't wanna toast your pizza. You only wanna toast the bread of the sandwich. Right? So you might want to, You might just go ahead and say toast the the bread, and it's gonna say, hey. Hold on. I see that you could toast a sandwich, But it's also possible that somebody is passing in a pizza in this case, and you haven't written any code that makes you check that it is a toastable food before moving in. Right. So type narrowing would be just as part of as part of that function, you would either check that it is a toastable food first before you go ahead and do the functions that are toasting Or you would convert like Scott said, you would convert the number to a string so that you're dealing with apples and apples before you go ahead and go through the rest of the function. Yeah.

Scott Tolinski

It. It's it's amazing how, like, how many times the food examples creep into the show. It's funny it's so funny that it would be like, it. We could have, like, a t minus or food was last mentioned.

Topic 7 09:13

Food metaphors

Scott Tolinski

Sandwiches were last mentioned x amount of days ago on the show because it always ends up going there. But I think they're examples. Definitely.

Scott Tolinski

So first off is going to be one of the easiest ways to type guard, something that you're going to see very commonly, and that's just checking the type of the thing in a conditional.

Scott Tolinski

You'll frequently see this as, like, type of variable is equal to a string. Right? If maybe you have, like, a, a union type that's either a string or a number. If you successfully wrap in an if statement, if this variable is type of string, then do this following thing, then that's going to fix that error because now you've added a an explicit check to make sure that the thing is a string before you try to use the string method. And I use this myself even in template code all over the place, it. In so JSX or TSX or Svelte template code, all of that can be happy with the methods you're trying to use or pass down as things get more narrow. Yeah.

Topic 8 10:19

typeof type guard

Wes Bos

That doesn't work with TypeScript types. So you couldn't say if it is a type of a dog or type of animal or any of the custom TypeScript types that you've created.

Wes Bos

And the reason behind it actually doesn't doesn't even work all that well with objects. And the reason behind that is because if you say type of like an array, it will tell you that it's an object, right? Like almost everything in JavaScript it. Pass your basic, what, strings, numbers, booleans, are just objects. So once you pass Those those sort of simple ones. There's a couple other ways you could check if something is a type. You could check if it has a property that you're looking for so you can use the property in object. Like, let's say you're trying to check if something was a podcast And you say, okay. I know that a podcast will have an m p three property. You could say if, m p 3 in podcast or MP 3 in audio, then go ahead. And in that case, you're checking that it has, and TypeScript will say, okay, I'll let that go because That's the only possible other type that's being passed in that would have an m p three property.

Topic 9 11:29

in and instanceof type guards

Wes Bos

But if you pass in 2 things that were totally separate, then I'm going to catch you on that. Right? So you could do prop in. You can also just say, if object dot property. So if media dot m p 3, Tied to using the dot notation is that if you're using classes, and extending prototypes, then that will also look up the prototype a chain, and that might not be what you want. So if you wanna actually check if the instances on the thing or not, you can use the in. Yeah. And you can also use

Scott Tolinski

instance of as well for this type of thing where, instance of will also check up c s. The prototype chain.

Scott Tolinski

So if you were to say let's say you had, a variable.

Scott Tolinski

Variable is an instance of a date, then you would know that you have access to the the date methods, that things that you would typically have on a date and not on a string. So in union types, you can always use instance of as well,

Wes Bos

to narrow the branch, so to say. Oh, that's that's a really good example. Actually, I was just like I was Writing examples of like custom classes, but like the date is one that's built in, right? Anything that you need to use new on In JavaScript, so new date is an example. Or if you create your own class and you want to say new food or new sandwich. Then then you can check if it is an instance of because that object has been generated as an instance of, one As an instance of the one they created. I'm sorry. Can't speak.

Scott Tolinski

Yeah. Definitely, something that you probably hit more With any types of classes or complex objects. Yeah. More in object oriented

Wes Bos

object oriented programing is is much more, comment for you to to run into that type of thing, but it's it's it's you could still hit that and react as well, so You definitely need that in your tool belt.

Wes Bos

And the last 1 we have here is just a custom type guards, and that is Not anything that we didn't just talk about, but there is an idea in TypeScript.

Wes Bos

Instead of stuffing your functions full of if statements, Yes. You can take the logic out of those functions and just put them in their own functions.

Topic 10 13:44

Custom type guard functions

Wes Bos

So you could say function is a sandwich that accepts a type of food.

Wes Bos

And then from that you can just return If any of the the type of the in the proper property check or the instance of, and that will return a boolean.

Wes Bos

But the only like the kind of like the weird thing or the interesting thing about that in TypeScript is the return type of a type guard.

Wes Bos

Again, remember, a type guard is just a function that returns whether something is a type or not using all the methods we just talked about.

Wes Bos

But the return type is not a boolean. It's a return.

Wes Bos

Something is is like the property is the type. So I've never there's nothing else in TypeScript like that. You're always returning a string, a number of boolean, a custom type interface. But in this case, you say, I am specifically making this a type guard by saying in my case, the food argument that is passed to the function is sandwich, And that will tell TypeScript this is a type guard and is good enough to check for what I want. Interesting that I've I've never

Scott Tolinski

ever done that before, And this is my, honestly, my first time seeing this as a strategy. I've just never had to reach for this, but I think this is really neat. I was looking into it, and I was like, why not just put a if statement inside the

Wes Bos

inside your function? Right? That's what I usually do, and that's good enough.

Wes Bos

But I guess The idea behind it I saw was that some people were saying you shouldn't be putting that logic in your function because that is not what your function does.

Wes Bos

So it's better to move it out into its own function, which I can see. And then also it's it's more reusable if you have a much more complex type guard.

Wes Bos

It's not a good idea to replicate that check 3 or 4 times. In my case, it's almost always a one liner. Who cares? Right. But, it's nice to stick it in a separate function, I guess. It seems like it's the classic

Topic 11 15:53

Abstracting type checks

Scott Tolinski

abstract away Sweep under the the Yeah. Ugly stuff underneath the rug. Right? You have all these ugly if checks. You can just sweep it into a singular function that does the the check for you. It. I think that the syntax is the blank is food is sandwich as the return type is is really interesting as well.

Scott Tolinski

Yeah.

Scott Tolinski

Now I also saw a type narrowing with this is. Have you have you seen that, Wes? Oh, I don't think so. This is. Yeah. So, This is an interesting one where you can use this is type where you're basically defining the type of this.

Topic 12 16:30

this is type narrowing

Scott Tolinski

So you can specify this is type in the return position for methods and for methods in classes and interfaces.

Scott Tolinski

When mixed with type narrowing, the type of the tag target object would be narrowed to the specified type. So you're basically saying Inside of the constructor.

Scott Tolinski

This is tight. It's so funny to say. Okay. Yeah. It goes inside a constructor.

Scott Tolinski

Correct.

Wes Bos

Okay. Okay. That makes sense because it's if it's if it's being bound to that. Interesting.

Wes Bos

Especially if it's, like, being extended. Yeah. See, b and o o p. It's not something that I do a whole lot of. I bet where that is handy is if you have a base type like food and then you have Something that is extending it and you you run super and then super will run the it. Original constructor first before you go ahead and and finish your your constructor of the extended type. I wonder if it's it's handy in those use cases.

Wes Bos

Yeah. Tweet us at syntax of m if you know because I again, I'm not a big object oriented programmer, so it's definitely,

Scott Tolinski

not one of those areas I've touched Yeah. It's one of those things that I see in the docs here, and I say that's neat.

Scott Tolinski

And then I never run into that issue in my code. So maybe there'll be someday when I'm Actually writing object oriented programming where the perfect opportunity to use this is will come up, and I'll I'll rejoice. But, Yeah. So far, I have not used it myself personally. I would love to see some real practical examples of it. Next one is this is kind of in the same area of type

Wes Bos

CSC Unions. So often a union is basically a list of types where it could be this or it could be this or it could be this. And often within those, Let's say you have 3 types, often within or let's go back to my sandwich or pizza example. Right? Sandwich or pizza. They both I have their own properties. Like a pizza would have toppings and, a sandwich would have bread type, but they Also, we'll share things like, like a best before date is is the example that I've used. Right? You were so good with these food metaphors.

Topic 13 18:06

Discriminated unions

Wes Bos

Right.

Wes Bos

So if you a discriminating union is that, you are passing in a value of food, and you have to check on those those fields that are different from each other. Right? Like you say, okay. The example, The TypeScript docs is really good as well as network state. Your network can either be loading, it could be failed, or it could be a success.

Wes Bos

And the network state will have 3 different possible states and the network state will share possible state values, But then they will not share things like a successful response or an error will be will be different. Right? And being able to check for those values Inside of your function is important.

Scott Tolinski

Otherwise, TypeScript is gonna yell at you again. Yeah. TypeScript frequently likes to yell at you, and that is one of the things that, like, Kind of turns people off of TypeScript occasionally, right, because it's yelling at you so much. But I do think being able to control types from type narrowing it. Using many of these, techniques that we talked about in this episode is, like, one of the key ways that you go from being like, TypeScript is controlling my life too. I'm controlling TypeScript.

Wes Bos

Yeah, I found and I think I still find this, but especially When I started TypeScript, it was just like, like it's making you. And it's not that TypeScript is is being, annoying.

Topic 14 19:55

Controlling vs being controlled by TS

Wes Bos

Well, it is it is annoying, but it's it's doing it because, there's a possibility that you could goof this up, or There's a possibility that somebody passes the very basic example that we didn't cover here is that it's possible that this thing is going to be undefined.

Wes Bos

And if you do not handle the case for this thing being undefined, then at some point you're going to have a bad day and your application is going to crash or You're you're gonna send out an email that has undefined in it. Like, my, I popped open something on my Google Google Home the other day and just said undefined. And I was like, that's a case.

Scott Tolinski

They did not properly account for that being undefined. Yeah. And and it should go to to say, you know, especially if you're new to TypeScript here. There are many times when it can feel like TypeScript is wrong. You're like, I've done everything I need to do here. TypeScript is wrong. And I'm gonna tell you straight up, that's never the case. It's always something that you have done, And it's always a an issue with the the types that you're narrowing or attempting to narrow. So if you are getting some of these errors and you can't figure it out, it. It's one of those core problems, I think, when you get into TypeScript is learning how to find and it. Just squish these types of issues in TypeScript because it is even though, like you said, it it is, you know, is yelling at you. It's at the end of the day, it is, you know, trying to save your butt. Or even it's looking now like,

Wes Bos

am I approaching this wrong? Unfortunately, you know, like, am I doing this wrong? Am I Like, I I find it really helpful to talk to people who have have hit that possible issue. And the question is not how do I fix this is Maybe do I need to step back 1 step behind that and and reshape how I wrote my types Or, or just like how I wrote this function. You know? Is TypeScript wrong? No. You are wrong.

Wes Bos

It's not me, is it? It might be. It's always cool. Yeah. I think that's it for me. Anything else to add here? No, I don't think so. Yeah. I think this is this nails it. Cool. Cool. Alright. Thanks for tuning in. Catch you on Wednesday.

Wes Bos

Peace. Peace.

Scott Tolinski

Head on over to syntax s.fm for a full archive of all of our shows. And don't forget to subscribe in your podcast player or drop a review if you like this show.

Share