Sometimes we want our function arguments to be able to accept more than 1 type; e.g. a string or an array. This lesson will show us how to assign more than 1 type to a variable with Typescript union types and type aliases.
[00:00] Annotating a variable looks like this. Annotating a variable to have more than one type looks like this. Thing is a string or number.
[00:09] This is called a Union type, and a Union type isn't just two types. It's as many as you want within the limitations of the machine.
[00:17] This is cool until you want to define a function whose argument can be all of these types, so let Return something equal a function that accepts something who can be any of these types, and then returns something.
[00:31] Luckily, TypeScript has aliases. All we've got to do is change the Let to Type, and the colon to an equals. Now let's add the type alias to the function argument. Let's call the function, run the compiler and the code, and we can see that we returned a cool guy.
[00:51] You probably want the function to behave differently depending on the type, so let's use a type guard. If type of something equals a string, or type of something equals a number, or type of something equals a Boolean, console log something.
[01:07] Here, I've used the Type of type card. We also have Instance of. If something is an instance of an array, we're going to join each of those things together. When you use a type card, TypeScript knows what the type is.
[01:21] TypeScript knows that something is an instance of an array, so that when I start to use something, all of the methods that are available on an array will be available, and for each, that's what I want.
[01:35] For each thing, add all the things together, both the IDE and compilers show no errors, because they know that something is an array.
[01:43] Let's console log our joined things. Call Return something. Let's try a number, run the compiler and the code. Sweet. Now let's try an array. Run the compiler and the code. It totally worked.
[02:02] The smarter way to do this would be to use the instanceof Array as the first condition, and just use an ounce for everything else. Let's see how this works. Run the compiler and the code. Sweet.
[02:16] One thing to watch out for is Union typing objects with Not Objects. Object with a Name property that's a string, with a Not Object. Here, I'm going to use my Type guard for the string, "Type of stuff equals string." All right, the IDE is cool with that. "Type of stuff.name equals string."
[02:41] We can see already that the IDE is pretty mad about this property right here, so let's see what the compiler says. "Property name does not exist on type string or an object with name string." Clearly, it exists on the object, but string doesn't have a name property.
[02:59] The compiler gets mad, because it tries to find the best common type between string and this object, but there is no common type. You also have to watch out when union typing object literals that don't share a common parameter.
[03:12] Here we have two objects with different parameters. Let's make a function that accepts a thing whose type is Cool Things. "If type of thing.name equals a string," and we can see already that the IDE is upset about the name property, but let's go all the way through to see what the compiler will say.
"[03:30] If type of thing.id equals a number, return it." Let's run the compiler. There's an error for each time the IDE displays an error. Here and here are these two, and here and here are these two. These are saying the same thing that we saw in this example, which is "Name does not exist on an object without a name."
[03:52] This one says, "ID does not exist on an object without an ID," and again, the compiler is getting mad, because there is no common type. However, if you have two objects with the same parameter, you can access that common parameter, but not the uncommon parameters.
[04:11] Let's say, "Return sat.cool or sat.lame," and we can see that the IDE is upset about the lame property, because it is not a common property, but it's cool with the cool property, because the cool property is a common property.
[04:26] To review, the Union type is defined by adding an Or pipe. The Type alias is kind of like a bar, except you're defining a type, not a variable. As of now, we have Type of and Instance of for type cards. Type cards let us differentiate between types and allow TypeScript to know what those types are.
[04:45] If you Union type Objects with Not Objects, the compiler gets mad. If you Union type Objects without a common parameter, the compiler gets mad. If you Union type Objects with a common parameter, you can access that common parameter.
feel free to use Array.prototype.join instead of forEach ;)
Hi, I think it is now possible to perform some checking with union types and not having typescript yell at us. For example:
type foo = { id: number, name: string };
type bar = { count: number, age: number };
type foobar = foo | bar;
function getFooBar(foobar: foobar) {
if ("id" in foobar) {
// Here's my foo
// foobar.count or foobar.age do not exist
return foobar;
}
if ("count" in foobar) {
// Here's my bar
// foobar.id or foobar.name do not exist
return foobar;
}
}
If you paste the previous snippet into the typescript playground source panel and highlight every one of the return statements, you will see that typescript is taking into account that the first object is a foo and that the second is a bar.
I think example in demo.js has. a small mistake in Transcript, i.e., let thing = string | number | string[] | boolean; let returnSomething = (someThing: thing) => { if (typeof someThing === "string" || typeof someThing === "number" || typeof someThing === "boolean") { console.log("somthing = ", someThing); } }
shall be changed to
type thing = string | number | string[] | boolean; let returnSomething = (someThing: thing) => { if (typeof someThing === "string" || typeof someThing === "number" || typeof someThing === "boolean") { console.log("somthing = ", someThing); } }
@sumitj18s Thanks for that! I went ahead and got that fixed in the transcripts. (also noticed the typo 'somthing' and fixed that as well)
Sorry, but that voice is really amazing :)
Just reporting a typo:
let thing = string | number | string[] | boolean;
in the transcript should betype thing = string | number | string[] | boolean;
as in the video :)