
Lesson Description
The "Union Types" 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 explains union types in TypeScript using the pipe operator to combine multiple types into one, creating wider types. She demonstrates how to define union types, handle optional properties, and compose different types together to constrain TypeScript to expected value types. Anjana also discusses typing variables before assigning values in TypeScript to ensure type constraints are met during development.
Transcript from the "Union Types" Lesson
[00:00:00]
>> Anjana Vakil: Now, let's talk about this pipe that I keep hand-waving away What is that And this pipe represents a way to define what TypeScript refers to as union types The idea here is that it's sort of a way of telling TypeScript that the type that this value can be might be any of these types So if I have a variable number or string, I can say, "Hey, I'm not sure exactly what this is going to be, but I know it's not going to be an object
[00:00:38]
I know it's not going to be undefined or null or blah blah It's going to either be a number or a string." And that is what this type operator does when we're declaring a type And what this tells TypeScript is essentially, if we have—if we think of the number type as like the set of all numbers, and we think of the string type as like the set of all strings, as opposed to a literal type, which is just that one particular string, for example—by putting that pipe there, what we're doing is we're creating the union of these two sets, and so now we have a type that can be any of the numbers or any of the strings
[00:01:30]
So it's a way of kind of combining two types together to make one, what we'd call wider type So numbers over here, strings over here, number or string, all of it And similarly, we saw how the optional property gave us—the question mark gave us a number or string or undefined We could do the same with like, we could make a nullish number where this could be null
[00:02:05]
Whether or not that's a good idea is a different question But if it has a value that's not null, that value better be a number And so that's where if we try to assign a string or an object or anything else, we will make TypeScript mad because it says, "Hey, null is not assignable to the type you gave me, and the type you gave me was the union of the type string and number." So whatever value you give to this variable, it has to fit in that union
[00:02:51]
And similarly with our number or knowledge number, we can make it null, we can make it a number, but we can't make it anything else Can we make it an array Oh Oh my god, can I make it an array No, we cannot And here it's saying, "OK, you gave me a value of type string array." We're going to talk a little bit later about how did—I didn't type that—how did TypeScript know that this is a string array, but we're going to talk about that later
[00:03:32]
It's called inference But either way, it's like that's not one of the types that was in the union But what if I wanted it to be What if I wanted this to be able—oh sorry, let's make this something a little bit more sensible What if it's like, it could be a number or it could be a bunch of numbers I can even add more pipe operators to do something like number array
[00:04:03]
And now what this is saying is—maybe it's a little easier to read if I move the null to the end OK, so this is saying, "Hey, OK, maybe this number or numbers or null"—is maybe a better terrible variable name for it oops, What I'm saying is, OK, maybe this is something that like later I'm going to pass into like some all of the numbers and I have to handle the logic of maybe it's an array of numbers, maybe it's just one number
[00:04:42]
I can define a type like that using the pipe operator to add, in addition to a single number, we could have an array of numbers, or we might not have anything at all, we might have null And that then means that it's fine if I want to assign it to an array of numbers However, an array of strings No, no No, no, no Not going to work
[00:05:13]
But—and I don't know why you would want a type like this, but if I were to say to TypeScript, "I want a type that could either be a number or an array of strings or null," I have the power to do that Whether I want to use that power to do something like that is a much different question Question: What if you wanted to type in an array that had a mix of objects, arrays and numbers in an array
[00:05:48]
Great question Just to repeat it So what if I wanted an array that doesn't have just one kind of thing How do we do that Great question So, keeping in mind that we have now in our TypeScript syntax toolbox, we have our pipe operator to create union types, meaning a type that can be various subtypes And we have our array syntax to make something like a type string apply to every value of an array, so now we get an array of strings
[00:06:39]
We can put those together So if I wanted to make a number or string array—let me just put numbers or strings Alright And I want this to be able to do things like 1 or 2 or 5 or whatever We can actually type this Now, let's try to figure it out together So first of all, I'm going to need a colon Always And now let's say we wanted to make a number array, we saw that the syntax for that would be this
[00:07:19]
Now that's a perfectly valid type, but now TypeScript is complaining because those strings How do we fit those in And that's where we want this—the type that goes before the square brackets is the type of elements in the array Now, if we want that type to be wider, we can actually tell TypeScript a different type here
[00:07:59]
Like, for example, if I say in parentheses—and we'll talk about the parentheses in a moment—I want a type that is either a number or a string That's a type of value Number or a string, right Like we saw that here And then with these parentheses we're saying, "OK, now that type, make an array of it Make an array of values that are each of type number or string." And now all of these values work, but something else will not
[00:08:41]
Now, OK, what is the deal with those parentheses Why did I need to put parentheses here around this union type I didn't need it here, although I could add it, I think Yeah, but it's not necessary, but before this array, it is Now, any guesses what would happen if I didn't have these parentheses It would evaluate out separately, right
[00:09:15]
So it would be either a number, right, or string array So similar to in JavaScript, the parentheses tell it, "Hey, look at the stuff inside the parentheses, and then look at the next stuff." Whereas here, without that, this looks very similar to just saying like number or an all or whatever is on the right-hand side here, and that's why now it's saying, "Hey, wait a minute
[00:09:49]
You said that number singular or strings array can have values that are either one number or an array of strings." And so this array that you gave me with a mix of stuff, that doesn't work because this is supposed to be a string array What if I do number or strings array equals 5 Fine Number or strings array equals 5 in an array as a string
[00:10:32]
Fine Number or strings array equals just the string 5 No go, because this is supposed to either be one number or an array of strings And so similarly, if I try to do number or strings array equals array of numbers, uh uh You didn't say it could be a number array You said it had to be a string array Now, if I wanted, let's say for either like 567, as strings, or 123 to work, can anybody figure out how I would make a type that allows this
[00:11:23]
Sorry, let me get rid of this here Can we make one little change to our type here that would allow for an array of numbers Add the brackets Add brackets after number exactly So now, because of the order of operations, very similar to how we're used to it in JavaScript, this is saying, "OK, an array of numbers, great, an array of strings, great." Now what if I give it—so where did I just—undo my—OK, sorry
[00:11:57]
Now what if I give it an array of mixed numbers and strings No go, because that is a different type, and if we look at this error message, we'll see these parentheses are indicating that TypeScript says, "Hey, OK, this is an array What's it an array of It's an array of elements that are either a number or a string." And that is not the same thing as an array of elements that are all numbers or an array of elements that are all strings
[00:12:37]
So, this is how we can start to compose these different types of types together to make sure that we're constraining TypeScript to the actual types of values that we're wanting in our code Question: When you do like let n equal or colon number, is there any like problem with just having a named variable with a type, but not using it anywhere
[00:13:13]
Right, so if we have like in our in just JavaScript code, if we have like let uninitiated colon—I just, I typed the equals out of muscle memory That's fine You put a semicolon Oh yeah, sorry, semicolon That's, yes If I were to like console log this, right, console, console log uninitiated I would get guesses Undefined, 'cause I haven't defined it
[00:13:43]
I haven't given it a value And this is just JavaScript We're not in TypeScript world yet And so later with let, with let, I can just say, "Hey, there's going to be a variable here," and not give it a value until later, like maybe, you know, somewhere else in the codebase, it's like now I exist And now, if I were to console log it, I get the value
[00:14:20]
All we're doing, this is all valid JavaScript This is just how let variables can exist before their values do What we're doing in TypeScript is we're just adding a little bit of information about eventually when this gets a value, it better be a type of string And so if I try then to, let's say, give it an array of strings
[00:15:02]
Ah ah ah, no, no, you told me this was supposed to be a single string, not an array of strings However, as long as I don't give it a value, TypeScript's just going to say, "Hey, hey, hey"—and this is where the settings, we'll talk about this later, like how strict we want TypeScript to be—it's like, "Hey, you're trying to use this variable that you didn't actually give a value to
[00:15:32]
You probably didn't want to do that." And so that's really the cool thing about being able to type variables before they have values is that if we didn't do that, I mean, TypeScript has no way of knowing that we don't want this to be undefined Could be undefined, no reason not to But if I say, "Hey, this better be a number," and then I try to log undefined before I've actually defined a value for this, it's going to complain
[00:00:00]
So, this typing variables before their values exist is just sort of a way we can constrain the types of values that eventually can get populated into that variable.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops