1 00:00:00,180 --> 00:00:01,770 - One of the more powerful features 2 00:00:01,770 --> 00:00:03,180 that you're going to use in TypeScript 3 00:00:03,180 --> 00:00:06,510 that I absolutely love is called the discriminated union, 4 00:00:06,510 --> 00:00:09,120 or you may hear it called the discriminating union. 5 00:00:09,120 --> 00:00:10,680 And essentially it's a union 6 00:00:10,680 --> 00:00:12,990 that allows you to determine which part of the union 7 00:00:12,990 --> 00:00:16,650 you're in based on some specific field or flag. 8 00:00:16,650 --> 00:00:18,750 To figure out why you want this and what this is, 9 00:00:18,750 --> 00:00:20,910 let's take a quick look at this code for a second. 10 00:00:20,910 --> 00:00:23,760 We have a type which is a user API response. 11 00:00:23,760 --> 00:00:26,670 This response can either be a success or an error. 12 00:00:26,670 --> 00:00:28,470 And in the case that we have an error, 13 00:00:28,470 --> 00:00:30,977 we're going to populate this error message with a message. 14 00:00:30,977 --> 00:00:33,120 And in the case that we have a success, 15 00:00:33,120 --> 00:00:35,700 we're gonna populate this data with an ID and a name 16 00:00:35,700 --> 00:00:38,250 for the user that we just tried to query for. 17 00:00:38,250 --> 00:00:41,010 Now in order to make sure our type works fine in both cases, 18 00:00:41,010 --> 00:00:42,570 we need to make sure our data is optional 19 00:00:42,570 --> 00:00:44,040 and our error message is optional, 20 00:00:44,040 --> 00:00:45,900 because when our status is error, 21 00:00:45,900 --> 00:00:47,880 we're not going to have any data at all, 22 00:00:47,880 --> 00:00:49,500 and when our status is success, 23 00:00:49,500 --> 00:00:51,840 we're not going to have any error message at all. 24 00:00:51,840 --> 00:00:55,200 But I know for a fact that when my status is successful, 25 00:00:55,200 --> 00:00:56,820 I will always have data. 26 00:00:56,820 --> 00:00:58,290 And when my status is an error, 27 00:00:58,290 --> 00:01:00,540 I will always have an error message. 28 00:01:00,540 --> 00:01:02,340 So this leads to some interesting code, 29 00:01:02,340 --> 00:01:04,200 because as I have this written, 30 00:01:04,200 --> 00:01:07,290 data and error message are always optional no matter what. 31 00:01:07,290 --> 00:01:09,360 So even when I check for a successful response, 32 00:01:09,360 --> 00:01:10,680 I'm getting an error in TypeScript 33 00:01:10,680 --> 00:01:14,460 because according to my type, my data could be undefined, 34 00:01:14,460 --> 00:01:16,080 even though I know for a fact, 35 00:01:16,080 --> 00:01:19,200 if I have a successful status, my data should be there. 36 00:01:19,200 --> 00:01:20,400 Same thing with my error message. 37 00:01:20,400 --> 00:01:22,890 I know if I have an unsuccessful status, 38 00:01:22,890 --> 00:01:25,260 I know my error message should be there. 39 00:01:25,260 --> 00:01:27,060 So the way we get around this problem 40 00:01:27,060 --> 00:01:29,490 is by using a discriminated union. 41 00:01:29,490 --> 00:01:30,690 The best way to think about that 42 00:01:30,690 --> 00:01:33,960 is breaking our response into all the different permutations 43 00:01:33,960 --> 00:01:34,800 we know are possible. 44 00:01:34,800 --> 00:01:36,780 So we know the error status is possible 45 00:01:36,780 --> 00:01:38,190 and the success status is possible. 46 00:01:38,190 --> 00:01:41,070 So let's create two different types of responses. 47 00:01:41,070 --> 00:01:44,400 The first one is going to be a success response. 48 00:01:44,400 --> 00:01:46,050 And in that case, if we look at our code, 49 00:01:46,050 --> 00:01:48,630 I know my status here is going to be success, 50 00:01:48,630 --> 00:01:49,680 so I know it's just going to be 51 00:01:49,680 --> 00:01:52,110 the hard coded string of success. 52 00:01:52,110 --> 00:01:53,790 And then I know that I'm going to have my data, 53 00:01:53,790 --> 00:01:56,150 so I'll copy this over, but I'm not gonna make it optional. 54 00:01:56,150 --> 00:01:57,810 If I have a successful status, 55 00:01:57,810 --> 00:01:59,790 I know that my data's gonna be there. 56 00:01:59,790 --> 00:02:00,840 Now let's copy this down. 57 00:02:00,840 --> 00:02:03,120 This is going to be for our error response. 58 00:02:03,120 --> 00:02:05,670 Our status is going to be an error every single time 59 00:02:05,670 --> 00:02:06,503 no matter what. 60 00:02:06,503 --> 00:02:08,100 And instead of having a data, 61 00:02:08,100 --> 00:02:09,780 we're gonna have an error message, 62 00:02:09,780 --> 00:02:12,050 and this will no longer be optional. 63 00:02:12,050 --> 00:02:13,920 So now I've created two different types. 64 00:02:13,920 --> 00:02:16,740 One for what happens when I have a successful response, 65 00:02:16,740 --> 00:02:19,320 and one for what happens when I have an error response. 66 00:02:19,320 --> 00:02:21,030 So instead of trying to combine these together 67 00:02:21,030 --> 00:02:22,770 into one complicated thing 68 00:02:22,770 --> 00:02:24,450 that has a bunch of optional parameters, 69 00:02:24,450 --> 00:02:27,900 I've broken them out into two specific different types. 70 00:02:27,900 --> 00:02:30,450 Then what I can do is for my overall general type, 71 00:02:30,450 --> 00:02:33,390 I know I'm going to be in one of these two scenarios, 72 00:02:33,390 --> 00:02:35,100 so I can just use a union. 73 00:02:35,100 --> 00:02:37,470 So I can say that we have our success response, 74 00:02:37,470 --> 00:02:40,200 or we're gonna have our error response just like that. 75 00:02:40,200 --> 00:02:41,033 And now as you can see, 76 00:02:41,033 --> 00:02:43,290 this is just a combination of one of those two. 77 00:02:43,290 --> 00:02:45,030 And also by just doing that, 78 00:02:45,030 --> 00:02:46,860 you'll notice immediately all of these errors we had 79 00:02:46,860 --> 00:02:48,450 in this function have gone away. 80 00:02:48,450 --> 00:02:49,860 And that's because of the power 81 00:02:49,860 --> 00:02:51,750 of these discriminated unions. 82 00:02:51,750 --> 00:02:53,160 So the way you can know that you're using 83 00:02:53,160 --> 00:02:55,170 a discriminated union is generally, 84 00:02:55,170 --> 00:02:57,750 you're going to have some type of field which is different 85 00:02:57,750 --> 00:02:59,370 between all of your different types. 86 00:02:59,370 --> 00:03:01,440 So in our case, our status field is different. 87 00:03:01,440 --> 00:03:03,480 So if we have a status of success, 88 00:03:03,480 --> 00:03:05,630 we will always be in this particular type. 89 00:03:05,630 --> 00:03:06,840 If our status is error, 90 00:03:06,840 --> 00:03:09,120 we will always be in this particular type. 91 00:03:09,120 --> 00:03:10,680 You'll very often see this with like, 92 00:03:10,680 --> 00:03:12,300 different key values for example, 93 00:03:12,300 --> 00:03:14,520 for like, statuses or something like that. 94 00:03:14,520 --> 00:03:16,980 Now if we check for a status of success, 95 00:03:16,980 --> 00:03:19,590 we know that the type of our data here for our response 96 00:03:19,590 --> 00:03:21,780 is always going to be a successful response. 97 00:03:21,780 --> 00:03:24,930 You can see it has changed the type to a success response, 98 00:03:24,930 --> 00:03:27,660 because that is the only one of our keys in this union 99 00:03:27,660 --> 00:03:29,610 that has a successful status. 100 00:03:29,610 --> 00:03:31,860 While down here where we don't have a successful status, 101 00:03:31,860 --> 00:03:34,007 you can see our response is set to an error response. 102 00:03:34,007 --> 00:03:37,110 'Cause of our two options, this one is the only one 103 00:03:37,110 --> 00:03:39,630 that does not have a status of success. 104 00:03:39,630 --> 00:03:42,450 And now my data is automatically a required field, 105 00:03:42,450 --> 00:03:43,830 so I know it's always gonna be there 106 00:03:43,830 --> 00:03:45,720 and I don't have to do any weird if checks 107 00:03:45,720 --> 00:03:46,920 to determine if it's there. 108 00:03:46,920 --> 00:03:49,200 Same thing with my error message down here. 109 00:03:49,200 --> 00:03:51,180 Now the important thing to understand about this 110 00:03:51,180 --> 00:03:53,340 is you can only use literal values 111 00:03:53,340 --> 00:03:55,350 when you're trying to do a discriminated union. 112 00:03:55,350 --> 00:03:58,140 So if I were to try to say that this is a string, 113 00:03:58,140 --> 00:04:00,480 and my status down here is a number, 114 00:04:00,480 --> 00:04:01,920 this will no longer work. 115 00:04:01,920 --> 00:04:03,970 Even if I do this like, typeof, 116 00:04:05,130 --> 00:04:08,250 my status is equal to string, 117 00:04:08,250 --> 00:04:10,050 and if I spell all of that properly, 118 00:04:10,050 --> 00:04:12,600 you'll notice it still doesn't actually discriminately 119 00:04:12,600 --> 00:04:14,220 unionize this for me. 120 00:04:14,220 --> 00:04:16,290 And that's because it only works with literal values, 121 00:04:16,290 --> 00:04:18,330 so the fact that these are strings versus numbers, 122 00:04:18,330 --> 00:04:19,170 that doesn't work, 123 00:04:19,170 --> 00:04:21,180 it only works with those literal values of like, 124 00:04:21,180 --> 00:04:22,770 strings, numbers and so on. 125 00:04:22,770 --> 00:04:24,750 That's perfectly okay because most places 126 00:04:24,750 --> 00:04:26,820 that you want to use a discriminated union, 127 00:04:26,820 --> 00:04:28,380 you're going to have different things, 128 00:04:28,380 --> 00:04:31,050 such as a status or some other key where you have 129 00:04:31,050 --> 00:04:33,450 a bunch of different types that this thing can be. 130 00:04:33,450 --> 00:04:35,970 And very often you'll see this inside of a switch statement. 131 00:04:35,970 --> 00:04:39,390 So for example, we're going to switch on our status, 132 00:04:39,390 --> 00:04:41,400 and then we'll have a case in particular 133 00:04:41,400 --> 00:04:42,570 where it's an error. 134 00:04:42,570 --> 00:04:44,940 And then inside of here, if I try to get my information, 135 00:04:44,940 --> 00:04:46,020 you'll see I only have access 136 00:04:46,020 --> 00:04:47,550 to an error message in a status. 137 00:04:47,550 --> 00:04:50,040 And that's because my error status is what's being used, 138 00:04:50,040 --> 00:04:52,643 since I made sure to check for that error right there.