Literal Union Return Types0:41
So what I mean by that is, imagine we have a function that is flipCoin, and it basically just returns the string head or tail, depending on some randomly generated number. Now, we don't really want to type the return of this function as a string, because that doesn't actually give us that much safety. If we accidentally made this return head or tails, or heads or tails, and we really wanted head or tail, and other parts of our code were relying on this, typing it as a string doesn't actually give us that much safety. So we would use a literal type. So we would say it either returns head or it returns tail. And this is how we do a literal type. We're actually doing a union of two literal types. So head is a literal type, and tail is a literal type. And we're taking the union of the two, basically saying this function either returns one or the other.
So head is a literal type, and tail is a literal type. And we're taking the union of the two, basically saying this function either returns one or the other. We see we have no errors here. But if we accidentally make this tails, we're going to get an error here saying type head or tails is not assignable to head or tail. But of course, this is a mistake. So we just fix it like this. And then we can log this flipCoin if we really want to. We can run this. We can console.log. So we got a head.
Introducing Enums and Values2:12
So we have an enum for suit. And we basically say a suit can be hearts, spades, diamonds, or clubs. And if I try and console.log out suit.spades, we will get the number one. And that is because enums are zero index and spades is at index one in this enum. So it's not actually the value for spades. It is the index of spades within the enum. So of course, we could represent this as a literal union again like we did with heads and tails. And type suit. So type is a new bit of syntax that we haven't been introduced to yet. It is very similar to the interface keyword that we saw in the last two lessons.
Enum-Based Discrimination Function3:47
Like we just don't care. We just want to constrain it. So one reason we might want to do this completely trivial function. I've just copied and pasted the definition of what all the suits mean somewhere off the internet. I have no idea if this is true or not. But let's say we have a function that returns the meaning of a suit. And we give it a suit. So here we are typing. We give it a suit. A suit is an enum.
We give it a suit. A suit is an enum. And we check if it's suit.hearts is equal to the suit we're given. Then return the definition for hearts. So here is a prime example of something. We want to either constrain the possible suits. Or in this case more specifically we want to differentiate or discriminate is the word you would use in TypeScript. And we'll cover type discrimination later again in much more detail. But if we wanted to discriminate of the suit. Whether it's a heart, spades, diamonds or clubs.
We have logged out the value of spades. Even though it's an enum. So yes in a sense we do have a value here. But now let us log out the meaning again. And we can see everything still works as expected. But you'll notice here when we are logging out our suit meaning. We're still accessing the value of the enum. We're still doing suit.clubs. When I say we don't care what the value is. It means because we never actually consume the value of the enum in our code.
Enums vs Literal Strings6:30
When I say we don't care what the value is. It means because we never actually consume the value of the enum in our code. I cannot just replace this with the literal string clubs. TypeScript will throw an error. It will say argument of type clubs is not assignable to parameter of type suit. Even though suit has a clubs enum with a value of clubs. I can't just give it this value. This is a literal value. And we can't use literal values on enums. So if for example we were trying to.
And we can't use literal values on enums. So if for example we were trying to. If this was hooked up to a frontend form. It's a view or react component. We have a form input and the user types in a suit. And we return the meaning of that suit. We couldn't just link this up. Using like the direct user input. Because they would type the string clubs. Or you know lowercase.
Because they would type the string clubs. Or you know lowercase. And we wouldn't just be able to do this. Because again it's an enum. We have to pass in an enum. So we would have to do some transformation code. To then get suit.clubs. So what are some cases where you might not actually care about the value. You just want to discriminate between some finite set of values. Examples are anything that is contained within your code.
When to Use Enums7:33
You just want to discriminate between some finite set of values. Examples are anything that is contained within your code. So that doesn't cross an API boundary. Doesn't cross a user interface boundary. Doesn't cross a database boundary. If it's just some logic within your code. Then an enum is a perfectly suitable solution. That being said. If I use enums fully contained within my code. I tend not to use these string enums.
If I use enums fully contained within my code. I tend not to use these string enums. Because there are slight differences in compile and runtime behavior. Based on how TypeScript compiles this code to JavaScript. Whether you've used a numeric indexed enum or a string enum. And also while I think string enums are somewhat more readable. They don't actually really give you anything. Other than debugging for logging out the value.
