1 00:00:00,210 --> 00:00:01,170 - We have finally come 2 00:00:01,170 --> 00:00:03,720 to the most complicated part of TypeScript, 3 00:00:03,720 --> 00:00:04,553 but honestly something 4 00:00:04,553 --> 00:00:07,230 that can be incredibly useful in your code. 5 00:00:07,230 --> 00:00:08,760 Take for example, this really simple code 6 00:00:08,760 --> 00:00:10,590 where we're trying to select an input element 7 00:00:10,590 --> 00:00:12,000 that has the class of input 8 00:00:12,000 --> 00:00:14,340 and then we're trying to get the value of that input. 9 00:00:14,340 --> 00:00:15,870 Well, TypeScript is throwing an error here 10 00:00:15,870 --> 00:00:17,310 essentially saying the "Property value 11 00:00:17,310 --> 00:00:19,170 does not exist on the type of Element" 12 00:00:19,170 --> 00:00:20,310 and that's because query selector 13 00:00:20,310 --> 00:00:22,200 returns an element object to you, 14 00:00:22,200 --> 00:00:23,610 or null if it can't find anything, 15 00:00:23,610 --> 00:00:26,100 which is why I'm making sure to check here for null first. 16 00:00:26,100 --> 00:00:27,810 But the problem is, is it's just given me 17 00:00:27,810 --> 00:00:31,620 the most generic HTML element that's possibly imaginable. 18 00:00:31,620 --> 00:00:33,540 It doesn't tell me that this is an input element 19 00:00:33,540 --> 00:00:35,250 which has a value property, 20 00:00:35,250 --> 00:00:37,140 'cause like divs and stuff don't have values. 21 00:00:37,140 --> 00:00:38,460 So in order to tell query selector, 22 00:00:38,460 --> 00:00:41,190 I'm actually getting an input element instead, 23 00:00:41,190 --> 00:00:43,020 you need to pass in these angle brackets, 24 00:00:43,020 --> 00:00:45,180 so put two angle brackets and inside there 25 00:00:45,180 --> 00:00:47,350 you put the type of the generic you wanna pass along. 26 00:00:47,350 --> 00:00:51,030 So in my case, I want to have an HTMLInputElement, 27 00:00:51,030 --> 00:00:53,850 now by doing that I fixed all of my different errors. 28 00:00:53,850 --> 00:00:56,100 This right here where you see this angle bracket syntax, 29 00:00:56,100 --> 00:00:57,510 where you put types inside of it, 30 00:00:57,510 --> 00:01:00,000 this is a generic insight of TypeScript. 31 00:01:00,000 --> 00:01:02,520 Essentially this query selector function is saying, 32 00:01:02,520 --> 00:01:05,280 I can accept multiple different types of things 33 00:01:05,280 --> 00:01:07,590 or return multiple different types of things 34 00:01:07,590 --> 00:01:08,520 and in order to figure out 35 00:01:08,520 --> 00:01:10,380 what I'm returning or what I'm accepting, 36 00:01:10,380 --> 00:01:13,560 you, the developer, need to pass it along extra information 37 00:01:13,560 --> 00:01:15,360 in the form of these generic types. 38 00:01:15,360 --> 00:01:17,310 You're saying, "Hey, I'm trying to get an element. 39 00:01:17,310 --> 00:01:21,030 And the type of that element is an HTML input element." 40 00:01:21,030 --> 00:01:22,680 Now it's a little bit difficult to really see 41 00:01:22,680 --> 00:01:24,000 exactly how this is working 42 00:01:24,000 --> 00:01:26,490 until you actually start to write your own generics though. 43 00:01:26,490 --> 00:01:28,680 So let's practice writing a generic. 44 00:01:28,680 --> 00:01:30,360 We're gonna create a really simple function 45 00:01:30,360 --> 00:01:32,370 that's just going to return the second element 46 00:01:32,370 --> 00:01:33,330 inside of an array. 47 00:01:33,330 --> 00:01:36,720 So we'll say getSecond, it's gonna take in an array 48 00:01:36,720 --> 00:01:39,120 and then all we wanna do is just return the second element, 49 00:01:39,120 --> 00:01:41,550 which is index one like that. 50 00:01:41,550 --> 00:01:42,660 Now let's create an array, 51 00:01:42,660 --> 00:01:45,570 we'll say const a equals 1, 2, 3, 52 00:01:45,570 --> 00:01:48,090 and what I wanna do is I want to be able to pass this a 53 00:01:48,090 --> 00:01:51,420 to getSecond so we can pass that array inside of there 54 00:01:51,420 --> 00:01:55,220 and we'll just get the value from that, just like that. 55 00:01:55,220 --> 00:01:56,400 So now what we need to do 56 00:01:56,400 --> 00:01:57,930 is we need to type this array object. 57 00:01:57,930 --> 00:01:59,250 Well what I could do is I could type it 58 00:01:59,250 --> 00:02:00,480 as an array of numbers. 59 00:02:00,480 --> 00:02:02,310 So I could say we have a number array 60 00:02:02,310 --> 00:02:03,300 and everything works fine. 61 00:02:03,300 --> 00:02:05,610 You can see this return value is going to be a number, 62 00:02:05,610 --> 00:02:08,610 which is what I expect, and this is passing in just fine. 63 00:02:08,610 --> 00:02:10,260 But now what happens if I create another array? 64 00:02:10,260 --> 00:02:11,310 We'll just call this one b 65 00:02:11,310 --> 00:02:14,070 and this one is gonna be an array of strings instead. 66 00:02:14,070 --> 00:02:16,350 So we'll just put a couple strings inside of here. 67 00:02:16,350 --> 00:02:18,150 And now I want to do this exact same thing, 68 00:02:18,150 --> 00:02:20,550 but I wanna pass in b instead. 69 00:02:20,550 --> 00:02:23,850 So we have our return from b and a return from a, 70 00:02:23,850 --> 00:02:25,350 well now I'm obviously getting a problem 71 00:02:25,350 --> 00:02:27,510 because this is a string array 72 00:02:27,510 --> 00:02:30,000 and I'm trying to accept a number array up here. 73 00:02:30,000 --> 00:02:31,380 So you may think, "Okay, well you know what, 74 00:02:31,380 --> 00:02:33,150 I'll go ahead and I'll add string into here 75 00:02:33,150 --> 00:02:34,530 as another one of my types 76 00:02:34,530 --> 00:02:35,820 and now everything's gonna work fine," 77 00:02:35,820 --> 00:02:38,370 but my return values are essentially a string or a number, 78 00:02:38,370 --> 00:02:40,320 even though I know in the case of a, it should be a number 79 00:02:40,320 --> 00:02:42,300 and in the case of b, it should be a string, 80 00:02:42,300 --> 00:02:43,200 so that doesn't work, 81 00:02:43,200 --> 00:02:44,100 and if I wanted to try to add 82 00:02:44,100 --> 00:02:45,630 a new array that uses Booleans, 83 00:02:45,630 --> 00:02:48,120 well obviously I need to infinitely expand this. 84 00:02:48,120 --> 00:02:48,953 You may think, "Okay, 85 00:02:48,953 --> 00:02:50,970 well I'll just make this in any array," 86 00:02:50,970 --> 00:02:51,803 but again, we have another problem 87 00:02:51,803 --> 00:02:54,690 'cause now our return values are all set to any. 88 00:02:54,690 --> 00:02:56,370 So there's really no way to do this 89 00:02:56,370 --> 00:02:57,420 with the knowledge we have, 90 00:02:57,420 --> 00:02:59,640 except for this is where generics come in. 91 00:02:59,640 --> 00:03:01,080 Generics allow you to essentially say 92 00:03:01,080 --> 00:03:03,030 that this could be any type at all, 93 00:03:03,030 --> 00:03:05,190 but that type is going to be something you pass in 94 00:03:05,190 --> 00:03:07,710 when you call the function or when you declare the type. 95 00:03:07,710 --> 00:03:09,720 When you create a function that you want to be generic, 96 00:03:09,720 --> 00:03:11,730 what you do is you put those same angle brackets in there 97 00:03:11,730 --> 00:03:13,830 right after the function name and inside of here 98 00:03:13,830 --> 00:03:15,900 is where you declare all your different generics. 99 00:03:15,900 --> 00:03:17,670 Function can have as many generics as you want, 100 00:03:17,670 --> 00:03:18,510 it doesn't matter. 101 00:03:18,510 --> 00:03:20,190 But what you do is you just declare them 102 00:03:20,190 --> 00:03:22,020 just like you would like the name of a type. 103 00:03:22,020 --> 00:03:23,040 That's how you think of a generic. 104 00:03:23,040 --> 00:03:25,470 It's essentially a type that you're passing in. 105 00:03:25,470 --> 00:03:27,570 Oftentimes you'll see this as T, 106 00:03:27,570 --> 00:03:29,460 but in our case we can be a little bit more specific 107 00:03:29,460 --> 00:03:32,760 where we can say that this is going to be our ArrayType, 108 00:03:32,760 --> 00:03:35,610 because that's what this thing specifically is. 109 00:03:35,610 --> 00:03:37,560 Now we have this type that we can pass in 110 00:03:37,560 --> 00:03:40,170 and we can use this type anywhere inside of our function. 111 00:03:40,170 --> 00:03:42,000 So for example, when we declare our array, 112 00:03:42,000 --> 00:03:44,880 we can say it is going to be of the type ArrayType. 113 00:03:44,880 --> 00:03:46,080 Just by doing that alone, 114 00:03:46,080 --> 00:03:47,640 we've actually fixed all of our code. 115 00:03:47,640 --> 00:03:50,160 You can see here this return value is set to a number 116 00:03:50,160 --> 00:03:53,040 and this return value down here for b is set to a string. 117 00:03:53,040 --> 00:03:54,840 And that's because what I'm calling 118 00:03:54,840 --> 00:03:56,580 this get second function, if I look at it, 119 00:03:56,580 --> 00:03:58,620 you can see that it's automatically inferring 120 00:03:58,620 --> 00:04:01,200 that this type right here for my array type is a number 121 00:04:01,200 --> 00:04:03,150 and my array is a number array, 122 00:04:03,150 --> 00:04:04,320 while when I call it with a string, 123 00:04:04,320 --> 00:04:05,970 you can see it's automatically inferring 124 00:04:05,970 --> 00:04:07,710 this string value as well. 125 00:04:07,710 --> 00:04:09,630 If you wanted, you could manually pass this in 126 00:04:09,630 --> 00:04:11,160 by putting the angle brackets and saying 127 00:04:11,160 --> 00:04:12,571 that this is going to be a number 128 00:04:12,571 --> 00:04:14,520 and this one is going to be a string. 129 00:04:14,520 --> 00:04:17,160 But oftentimes when you're using generics in TypeScript, 130 00:04:17,160 --> 00:04:18,690 it's smart enough to look at the values 131 00:04:18,690 --> 00:04:21,270 you pass into your parameters to actually determine 132 00:04:21,270 --> 00:04:24,090 what that generic is and you may never even need to pass in 133 00:04:24,090 --> 00:04:26,940 the actual generic value here, which is really nice. 134 00:04:26,940 --> 00:04:28,740 So I know this is a lot to digest right here. 135 00:04:28,740 --> 00:04:30,000 So I'm gonna do a quick recap 136 00:04:30,000 --> 00:04:30,833 before we start moving on 137 00:04:30,833 --> 00:04:33,420 to some more advanced concepts for generics. 138 00:04:33,420 --> 00:04:35,160 A generic can be used anywhere you want, 139 00:04:35,160 --> 00:04:37,590 whether it's a type and interface or a function. 140 00:04:37,590 --> 00:04:39,507 In our case, we're specifically using it in a function. 141 00:04:39,507 --> 00:04:41,430 And if you want to declare your function 142 00:04:41,430 --> 00:04:43,050 as a generic function, 143 00:04:43,050 --> 00:04:43,883 you need to make sure 144 00:04:43,883 --> 00:04:45,420 directly after the name of the function, 145 00:04:45,420 --> 00:04:46,800 you put the angle brackets 146 00:04:46,800 --> 00:04:48,750 and then you put all of your generics that you want. 147 00:04:48,750 --> 00:04:52,020 Again, we can have multiple types inside of here if we want 148 00:04:52,020 --> 00:04:54,180 and we can call them anything we want. 149 00:04:54,180 --> 00:04:56,190 Generally you like to use the same notation 150 00:04:56,190 --> 00:04:58,980 as you use with types, so CamelCase capitalized, 151 00:04:58,980 --> 00:05:01,140 but you can put as many as you want or as few as you want. 152 00:05:01,140 --> 00:05:04,200 In our case, we're using just one single generic. 153 00:05:04,200 --> 00:05:06,840 Then these generic values you can use anywhere 154 00:05:06,840 --> 00:05:09,300 you actually define your types for your function. 155 00:05:09,300 --> 00:05:11,310 So I can use them here in the parameters 156 00:05:11,310 --> 00:05:13,230 or I could use it in the return type, 157 00:05:13,230 --> 00:05:14,520 'cause I know this is going to return 158 00:05:14,520 --> 00:05:16,160 whatever my array type is. 159 00:05:16,160 --> 00:05:18,780 So you can use it anywhere you would use a normal type 160 00:05:18,780 --> 00:05:20,190 inside of your function. 161 00:05:20,190 --> 00:05:22,530 But the nice thing is is that this generic type 162 00:05:22,530 --> 00:05:25,140 can be anything, and when you call the function, 163 00:05:25,140 --> 00:05:27,240 you either explicitly pass along 164 00:05:27,240 --> 00:05:28,770 what the generic is going to be, 165 00:05:28,770 --> 00:05:30,570 in our case we pass along number 166 00:05:30,570 --> 00:05:32,796 and now essentially you have the exact same thing, 167 00:05:32,796 --> 00:05:35,130 but every word that you have array type, 168 00:05:35,130 --> 00:05:37,560 it's just replaced with the word number. 169 00:05:37,560 --> 00:05:39,690 That's essentially what happens when you use a generic. 170 00:05:39,690 --> 00:05:41,490 It's just replacing all the places 171 00:05:41,490 --> 00:05:42,990 where you have that generic type 172 00:05:42,990 --> 00:05:45,570 with the specific type that you pass in. 173 00:05:45,570 --> 00:05:47,460 Now the other way you can use these generics 174 00:05:47,460 --> 00:05:49,170 is by not passing in the generic 175 00:05:49,170 --> 00:05:52,140 and let it infer the generic if it is possible. 176 00:05:52,140 --> 00:05:55,020 In that case, you can see here we're passing a string array. 177 00:05:55,020 --> 00:05:57,330 So it knows that this array type should be a string. 178 00:05:57,330 --> 00:06:00,060 - And it just replaces all use cases of array type 179 00:06:00,060 --> 00:06:02,190 with the string parameter here to give you 180 00:06:02,190 --> 00:06:03,510 essentially a version of the function 181 00:06:03,510 --> 00:06:06,510 that only works with strings instead of a generic version. 182 00:06:06,510 --> 00:06:07,470 Now, generics are something 183 00:06:07,470 --> 00:06:09,630 that are fairly common in TypeScript, 184 00:06:09,630 --> 00:06:11,760 but mostly because you're going to be using them 185 00:06:11,760 --> 00:06:13,980 and not so much because you're going to be writing them. 186 00:06:13,980 --> 00:06:15,060 A lot of the generics that you use 187 00:06:15,060 --> 00:06:16,410 are already built into JavaScript 188 00:06:16,410 --> 00:06:17,430 or the libraries you use 189 00:06:17,430 --> 00:06:19,440 and you probably won't have to write too many of them. 190 00:06:19,440 --> 00:06:21,090 So knowing how to use them is more important 191 00:06:21,090 --> 00:06:22,500 than knowing how to write them. 192 00:06:22,500 --> 00:06:24,278 Another really great example of a generic 193 00:06:24,278 --> 00:06:27,420 is the map type or the set type inside of JavaScript. 194 00:06:27,420 --> 00:06:29,460 Let's just use sets 'cause it's a little bit simpler 195 00:06:29,460 --> 00:06:34,460 and let's just say here that const a is equal to a new set. 196 00:06:34,830 --> 00:06:37,410 Now if I hover over this, you can see it's a set of unknown, 197 00:06:37,410 --> 00:06:38,910 we'll get to what unknown is later, 198 00:06:38,910 --> 00:06:40,890 but if I wanted to give this set a specific type, 199 00:06:40,890 --> 00:06:41,723 I could say, you know what? 200 00:06:41,723 --> 00:06:44,880 This is a set of strings, because set takes in a generic 201 00:06:44,880 --> 00:06:46,380 and now I have this a, 202 00:06:46,380 --> 00:06:48,600 which is a set based on string values. 203 00:06:48,600 --> 00:06:51,060 So if I come in here and I want to add to this, 204 00:06:51,060 --> 00:06:53,550 I can add in strings and that's gonna be working fine. 205 00:06:53,550 --> 00:06:54,870 But as soon as I try to add in something 206 00:06:54,870 --> 00:06:55,703 that's not a string, 207 00:06:55,703 --> 00:06:57,630 you see I'm going to be getting an error. 208 00:06:57,630 --> 00:06:59,520 And if I were to pass this a default value, 209 00:06:59,520 --> 00:07:01,380 for example, I passed it a default string, 210 00:07:01,380 --> 00:07:03,270 you can see it's smart enough to actually infer 211 00:07:03,270 --> 00:07:04,920 that the type is going to be string 212 00:07:04,920 --> 00:07:06,890 based on that default value I passed in. 213 00:07:06,890 --> 00:07:08,610 So this is another really great use case 214 00:07:08,610 --> 00:07:11,130 for where you're going to be using a generic type. 215 00:07:11,130 --> 00:07:13,530 Same thing with maps except for maps are a little bit 216 00:07:13,530 --> 00:07:15,960 different because it actually accepts multiple generics. 217 00:07:15,960 --> 00:07:18,600 As you can see here, it's going to accept in a generic 218 00:07:18,600 --> 00:07:20,490 for the key as well as the value. 219 00:07:20,490 --> 00:07:22,702 So I could say this is going to be a key of string 220 00:07:22,702 --> 00:07:25,320 and a value of a number just like that, 221 00:07:25,320 --> 00:07:27,324 and now if I want to add values to this 222 00:07:27,324 --> 00:07:29,728 by coming into here and I want to say set, 223 00:07:29,728 --> 00:07:32,250 I'm gonna set a key here which is a string 224 00:07:32,250 --> 00:07:34,260 to a value that is a number and that works. 225 00:07:34,260 --> 00:07:35,670 But as soon as I try to change something, 226 00:07:35,670 --> 00:07:37,170 you know like obviously this is not gonna work 227 00:07:37,170 --> 00:07:38,760 'cause that's not a string. 228 00:07:38,760 --> 00:07:39,900 And again, if I were to pass it 229 00:07:39,900 --> 00:07:42,450 some default values inside of here, 230 00:07:42,450 --> 00:07:43,650 you can see that it is smart enough 231 00:07:43,650 --> 00:07:45,960 to actually infer all this information for me, 232 00:07:45,960 --> 00:07:47,610 'cause when I hover over this you can see 233 00:07:47,610 --> 00:07:50,820 it has that string number, generic type already inferred. 234 00:07:50,820 --> 00:07:52,860 Now let's talk about how we can actually set this 235 00:07:52,860 --> 00:07:54,300 inside of types as well. 236 00:07:54,300 --> 00:07:59,160 So let's type a type called an APIResponse, there we go, 237 00:07:59,160 --> 00:08:01,020 and this type is going to have some data 238 00:08:01,020 --> 00:08:02,340 which is going to be some type of object, 239 00:08:02,340 --> 00:08:03,900 I don't really know what it's going to be yet, 240 00:08:03,900 --> 00:08:06,150 and then it's going to have an optional error 241 00:08:06,150 --> 00:08:08,130 and this error is just going to be a Boolean, 242 00:08:08,130 --> 00:08:10,230 actually, so let's just change this like this, 243 00:08:10,230 --> 00:08:12,660 we'll say isError, there we go. 244 00:08:12,660 --> 00:08:13,710 So this is gonna be true or false, 245 00:08:13,710 --> 00:08:14,700 whether or not there's an error 246 00:08:14,700 --> 00:08:17,460 and then data is going to return whatever my data is. 247 00:08:17,460 --> 00:08:19,440 Now this is another great use case for generics 248 00:08:19,440 --> 00:08:21,510 because this data could be a lot of different types. 249 00:08:21,510 --> 00:08:22,620 Maybe I'm returning users, 250 00:08:22,620 --> 00:08:24,330 maybe I'm returning posts from a blog, 251 00:08:24,330 --> 00:08:26,250 I don't really know what this is gonna be. 252 00:08:26,250 --> 00:08:28,110 I'm gonna set this to a generic type. 253 00:08:28,110 --> 00:08:29,700 Oftentimes when you're using generics 254 00:08:29,700 --> 00:08:31,440 you'll see the word T being used 255 00:08:31,440 --> 00:08:33,030 in place of an actual name, 256 00:08:33,030 --> 00:08:35,520 or you can get more specific by calling this like TData. 257 00:08:35,520 --> 00:08:37,710 A lot of times you'll see things prefixed with a T 258 00:08:37,710 --> 00:08:39,330 to really denote that this is a type, 259 00:08:39,330 --> 00:08:41,790 instead of saying DataType like this, 260 00:08:41,790 --> 00:08:43,670 it's just a really common thing in generics. 261 00:08:43,670 --> 00:08:46,950 So now to actually make a type or an interface use generics, 262 00:08:46,950 --> 00:08:49,135 all you do is write after the name of the type or interface, 263 00:08:49,135 --> 00:08:51,510 use your angle brackets and put in the name 264 00:08:51,510 --> 00:08:54,426 of the thing you want, tn our case this TData. 265 00:08:54,426 --> 00:08:56,092 Now if I want to use this API response 266 00:08:56,092 --> 00:08:59,506 by saying that a is going to be a type of API response, 267 00:08:59,506 --> 00:09:01,470 I can come in here and I can say 268 00:09:01,470 --> 00:09:03,570 that we're gonna have some data which is an object, 269 00:09:03,570 --> 00:09:05,570 and then we're gonna have, this isError, 270 00:09:06,510 --> 00:09:09,810 which we're gonna set to false, there we go. 271 00:09:09,810 --> 00:09:11,190 I'm obviously getting into some errors 272 00:09:11,190 --> 00:09:13,650 because I'm not passing along my generic type, 273 00:09:13,650 --> 00:09:15,210 so what we could do is we could manually 274 00:09:15,210 --> 00:09:16,620 pass in the type that we want here. 275 00:09:16,620 --> 00:09:18,720 Or in my case I'm gonna create a brand new type. 276 00:09:18,720 --> 00:09:21,780 And this type right here is going to be for UserResponse. 277 00:09:21,780 --> 00:09:22,613 There we go. 278 00:09:22,613 --> 00:09:25,380 And this has some data that's going to be passed into here, 279 00:09:25,380 --> 00:09:26,460 as well as that isError, 280 00:09:26,460 --> 00:09:28,020 but instead of manually defining that, 281 00:09:28,020 --> 00:09:29,700 I can just say that this is going to be equal 282 00:09:29,700 --> 00:09:31,950 to essentially my API response. 283 00:09:31,950 --> 00:09:34,950 But the actual data inside of it is just going to be a user. 284 00:09:34,950 --> 00:09:37,050 So it's gonna have a name which is a string 285 00:09:37,050 --> 00:09:39,690 and an age, which is a number, just like that. 286 00:09:39,690 --> 00:09:42,330 So now this user response extends, essentially, 287 00:09:42,330 --> 00:09:45,750 this API response by overriding what this TData is. 288 00:09:45,750 --> 00:09:47,730 So I have a data and an error, 289 00:09:47,730 --> 00:09:50,450 but this data is specifically this type right here. 290 00:09:50,450 --> 00:09:52,680 So now if I say I have a user response, 291 00:09:52,680 --> 00:09:55,257 it's essentially the same exact code as this right here, 292 00:09:55,257 --> 00:09:56,550 but now you can see my data 293 00:09:56,550 --> 00:09:58,470 requires a name and an age property. 294 00:09:58,470 --> 00:10:01,980 So if I pass in a name and an age, 295 00:10:01,980 --> 00:10:05,130 you can see that now it is working just like I expect it to. 296 00:10:05,130 --> 00:10:05,970 And this is really great 297 00:10:05,970 --> 00:10:07,950 because now if I want to have an API response, 298 00:10:07,950 --> 00:10:10,290 that's going to be for example, a blog instead. 299 00:10:10,290 --> 00:10:12,450 Well now I can change this to be like title 300 00:10:12,450 --> 00:10:15,000 and this, you know, could be all there is for my blog, 301 00:10:15,000 --> 00:10:18,090 and now I can come down and I can create something brand new 302 00:10:18,090 --> 00:10:23,090 that's going to be for my blog response, change this to b, 303 00:10:23,670 --> 00:10:26,370 and now my data requires that title property here 304 00:10:26,370 --> 00:10:28,290 instead of the name and the age, 305 00:10:28,290 --> 00:10:30,360 as you can see, no more errors at all. 306 00:10:30,360 --> 00:10:32,880 So this is just like using the generics with a function, 307 00:10:32,880 --> 00:10:35,250 but instead we're now using it in a type. 308 00:10:35,250 --> 00:10:37,770 And if I wanted, instead of extracting this user response 309 00:10:37,770 --> 00:10:40,380 into its own type, I could just replace this down here 310 00:10:40,380 --> 00:10:42,030 and it's going to work exactly the same, 311 00:10:42,030 --> 00:10:43,830 using this extraction into another type 312 00:10:43,830 --> 00:10:45,570 just makes it a little bit easier to read sometimes 313 00:10:45,570 --> 00:10:47,490 and makes it more reusable. 314 00:10:47,490 --> 00:10:48,323 Now what happens though, 315 00:10:48,323 --> 00:10:49,860 let's just bring this back to how we had it before, 316 00:10:49,860 --> 00:10:53,490 if I wanted to specify a default value for my response, 317 00:10:53,490 --> 00:10:54,390 because let's say, you know, 318 00:10:54,390 --> 00:10:56,340 not all of my stuff has some data 319 00:10:56,340 --> 00:10:58,410 and by default it'll just have a status 320 00:10:58,410 --> 00:11:01,500 and maybe a lot of my responses have that default value. 321 00:11:01,500 --> 00:11:03,480 What I can do is I can say that by default 322 00:11:03,480 --> 00:11:05,010 this is equal to a specific value. 323 00:11:05,010 --> 00:11:06,180 So I can just say by default 324 00:11:06,180 --> 00:11:10,080 this is equal to a status with a number property. 325 00:11:10,080 --> 00:11:12,480 So by default, if I don't respond with a generic, 326 00:11:12,480 --> 00:11:15,270 when I define my API response, it's just going to use 327 00:11:15,270 --> 00:11:17,550 this value right here, status of number. 328 00:11:17,550 --> 00:11:19,350 So if I just get rid of all this code, 329 00:11:19,350 --> 00:11:21,840 I'm gonna bring it up here, there we go. 330 00:11:21,840 --> 00:11:23,391 And I'm gonna create a brand new variable 331 00:11:23,391 --> 00:11:28,001 and this is going to be my API response, whoops, 332 00:11:28,001 --> 00:11:31,830 APIResponse, and here we have our data. 333 00:11:31,830 --> 00:11:34,470 And I know by default that if I don't pass along a generic, 334 00:11:34,470 --> 00:11:36,420 it's going to have a status, we'll say 200 335 00:11:36,420 --> 00:11:39,570 and isError is going to be false just like that. 336 00:11:39,570 --> 00:11:41,100 And as you can see, that's working just fine, 337 00:11:41,100 --> 00:11:43,290 but as soon as I pass in a generic type here 338 00:11:43,290 --> 00:11:45,420 of whatever it's going to be, 339 00:11:45,420 --> 00:11:48,900 for example, name string that overrides this default value 340 00:11:48,900 --> 00:11:51,240 and now I need to change this to a name property 341 00:11:51,240 --> 00:11:53,370 which has a string value instead. 342 00:11:53,370 --> 00:11:56,280 This is a great way of doing a default value. 343 00:11:56,280 --> 00:11:57,810 Another thing that you may run into 344 00:11:57,810 --> 00:12:00,480 is that our data we know should always be an object, 345 00:12:00,480 --> 00:12:01,740 at least in this case we're assuming 346 00:12:01,740 --> 00:12:03,300 it's always going to be an object. 347 00:12:03,300 --> 00:12:06,120 So if I try to pass along something like string here, 348 00:12:06,120 --> 00:12:09,030 obviously this is going to work just fine as is, 349 00:12:09,030 --> 00:12:10,830 but I know that this should always be 350 00:12:10,830 --> 00:12:13,700 an object instead of like a string, a number or an array. 351 00:12:13,700 --> 00:12:15,690 So what I can do is I can also say 352 00:12:15,690 --> 00:12:17,820 that this is going to extend a particular value, 353 00:12:17,820 --> 00:12:19,380 for now I'm gonna remove the default value, 354 00:12:19,380 --> 00:12:21,360 so it's a little bit easier to see what's going on, 355 00:12:21,360 --> 00:12:24,150 but I can say this extends object 356 00:12:24,150 --> 00:12:25,290 and now I'm going to get an error, 357 00:12:25,290 --> 00:12:27,030 'cause string does not extend object. 358 00:12:27,030 --> 00:12:29,730 So this must be an object of some form 359 00:12:29,730 --> 00:12:31,620 in order to actually work. 360 00:12:31,620 --> 00:12:33,770 There we go, and now if we bring this back, 361 00:12:34,620 --> 00:12:36,630 you can see we no longer have any errors. 362 00:12:36,630 --> 00:12:38,280 This extend property is really great 363 00:12:38,280 --> 00:12:39,990 if you want to kind of constrain 364 00:12:39,990 --> 00:12:41,250 what your generic is going to be. 365 00:12:41,250 --> 00:12:43,800 'Cause a generic by default can be any type at all, 366 00:12:43,800 --> 00:12:45,630 every type in TypeScript is valid, 367 00:12:45,630 --> 00:12:47,462 but by making it extend other things, you're saying, 368 00:12:47,462 --> 00:12:50,460 you know what, I'm constraining this to only be objects. 369 00:12:50,460 --> 00:12:52,140 Or if I'm saying it extends a string, 370 00:12:52,140 --> 00:12:54,270 it must only be a string in our case, 371 00:12:54,270 --> 00:12:57,720 or maybe you're extending array, it must be an array. 372 00:12:57,720 --> 00:12:59,730 And if we bring this back to where we had object, 373 00:12:59,730 --> 00:13:01,620 I can still use the same default value, 374 00:13:01,620 --> 00:13:03,150 it just goes after my extend. 375 00:13:03,150 --> 00:13:05,880 So I could say status is going to be a number by default. 376 00:13:05,880 --> 00:13:08,040 So now if I don't pass anything in here, 377 00:13:08,040 --> 00:13:09,660 you can see it's going to expect me 378 00:13:09,660 --> 00:13:12,930 to pass along a status, which is a number. 379 00:13:12,930 --> 00:13:14,730 Now I'm gonna take this back down a little more bare bones 380 00:13:14,730 --> 00:13:16,320 where all it is is just a data, 381 00:13:16,320 --> 00:13:17,760 it can be literally anything. 382 00:13:17,760 --> 00:13:19,440 And in our case we'll just come in here, 383 00:13:19,440 --> 00:13:21,210 we'll say status number, 384 00:13:21,210 --> 00:13:23,550 just so our code is actually working, there we go. 385 00:13:23,550 --> 00:13:25,770 Now I want to talk about a built-in type in TypeScript, 386 00:13:25,770 --> 00:13:27,210 which is also a generic, 387 00:13:27,210 --> 00:13:29,280 one that you are somewhat familiar with actually 388 00:13:29,280 --> 00:13:31,680 because it's a second way of defining arrays. 389 00:13:31,680 --> 00:13:33,780 So if we wanted to create an array here, 390 00:13:33,780 --> 00:13:36,900 we could say it's like 1, 2, 3, this is an array of numbers, 391 00:13:36,900 --> 00:13:38,520 make this b here, what I could do 392 00:13:38,520 --> 00:13:40,440 is I could type this as the array type, 393 00:13:40,440 --> 00:13:41,610 which is a generic type 394 00:13:41,610 --> 00:13:43,680 which takes in the type of the array. 395 00:13:43,680 --> 00:13:47,520 This is exactly the same as writing out number array 396 00:13:47,520 --> 00:13:49,440 just like this, they both do the exact same thing 397 00:13:49,440 --> 00:13:51,060 when it comes to creating an array. 398 00:13:51,060 --> 00:13:53,070 So you are kind of already familiar with generics, 399 00:13:53,070 --> 00:13:55,020 we just haven't been writing this as a generic, 400 00:13:55,020 --> 00:13:57,240 but both of those are the exact same thing, 401 00:13:57,240 --> 00:13:58,260 which is really interesting. 402 00:13:58,260 --> 00:14:00,510 So if I wanted my data to be an array of numbers, 403 00:14:00,510 --> 00:14:02,490 for example, 1, 2, 3, like that, 404 00:14:02,490 --> 00:14:06,603 well I could come in here and I can say array of numbers. 405 00:14:08,070 --> 00:14:11,127 Whoops, there we go, just like that. 406 00:14:11,127 --> 00:14:13,290 And I need to make sure I actually have my API response, 407 00:14:13,290 --> 00:14:14,760 so let's just back this up to where that was 408 00:14:14,760 --> 00:14:16,620 before I deleted it by accident, there we go. 409 00:14:16,620 --> 00:14:18,150 We have our API response up here 410 00:14:18,150 --> 00:14:21,450 and I can change this to an array of numbers, 411 00:14:21,450 --> 00:14:22,470 just like that. 412 00:14:22,470 --> 00:14:25,500 And now I can just pass in 1, 2, 3, 413 00:14:25,500 --> 00:14:26,730 and you can see that that works. 414 00:14:26,730 --> 00:14:28,410 So the important thing to note about this 415 00:14:28,410 --> 00:14:30,300 is first of all, there's this built-in type array 416 00:14:30,300 --> 00:14:33,024 which works just like the other array type, as you can see, 417 00:14:33,024 --> 00:14:35,820 both of these pieces of code do the exact same thing. 418 00:14:35,820 --> 00:14:36,690 The second thing to note 419 00:14:36,690 --> 00:14:38,640 is you can actually nest generics inside of each other. 420 00:14:38,640 --> 00:14:40,500 As you can see, we have this array generic, 421 00:14:40,500 --> 00:14:42,540 nested inside of our API response generic, 422 00:14:42,540 --> 00:14:43,650 it works just fine. 423 00:14:43,650 --> 00:14:46,170 A generic is just like any other type in TypeScript, 424 00:14:46,170 --> 00:14:48,540 it just requires you to pass along information 425 00:14:48,540 --> 00:14:51,360 that tells you what the generic type is supposed to be. 426 00:14:51,360 --> 00:14:53,220 That's all a generic really does. 427 00:14:53,220 --> 00:14:55,050 So at this point we understand generics, 428 00:14:55,050 --> 00:14:57,030 but we haven't really used them very much. 429 00:14:57,030 --> 00:14:58,200 So I want to create a function 430 00:14:58,200 --> 00:14:59,880 that's going to heavily use generics 431 00:14:59,880 --> 00:15:02,010 as well as many of the other features we've talked about 432 00:15:02,010 --> 00:15:03,300 inside of this section, 433 00:15:03,300 --> 00:15:05,520 in the last couple sections of the course, 434 00:15:05,520 --> 00:15:06,540 I'm gonna create a function 435 00:15:06,540 --> 00:15:08,700 and this function is just going to take an array 436 00:15:08,700 --> 00:15:09,810 and convert it to an object, 437 00:15:09,810 --> 00:15:11,580 so essentially it's gonna be an array of arrays 438 00:15:11,580 --> 00:15:13,443 and we'll say aToO, 439 00:15:14,880 --> 00:15:16,740 is what we'll call this, array to objects. 440 00:15:16,740 --> 00:15:18,360 It doesn't really matter what the name is. 441 00:15:18,360 --> 00:15:21,260 And the way I want to call this is I want to have an array 442 00:15:22,980 --> 00:15:24,840 and I want this array to be an array of arrays, 443 00:15:24,840 --> 00:15:27,990 so like the first thing is going to be like keyOne 444 00:15:27,990 --> 00:15:29,430 and then we're gonna give it a value, 445 00:15:29,430 --> 00:15:31,097 and then we're gonna say keyTwo, 446 00:15:32,460 --> 00:15:34,830 and we're gonna also give that a specific value, 447 00:15:34,830 --> 00:15:37,710 and we'll come in here, let's say keyThree, 448 00:15:37,710 --> 00:15:39,330 and this is also going to be a value, 449 00:15:39,330 --> 00:15:41,730 in our case, we'll give this one a Boolean value 450 00:15:41,730 --> 00:15:44,880 and make sure that this is inside of an array as well. 451 00:15:44,880 --> 00:15:46,890 Now you can see I have an array with three different arrays 452 00:15:46,890 --> 00:15:49,440 and I want to essentially convert this to an object 453 00:15:49,440 --> 00:15:50,447 that looks like this, 454 00:15:50,447 --> 00:15:55,447 keyOne is 1, keyTwo is 2, and keyThree is true. 455 00:15:56,580 --> 00:15:59,370 That's what I want to convert this to using my function. 456 00:15:59,370 --> 00:16:00,333 This is gonna require generics 457 00:16:00,333 --> 00:16:02,340 it's going to require a bunch of other things 458 00:16:02,340 --> 00:16:03,690 that we've already talked about. 459 00:16:03,690 --> 00:16:04,523 So the first thing we know 460 00:16:04,523 --> 00:16:07,140 that we need to pass into this is some type of array. 461 00:16:07,140 --> 00:16:09,150 And generally, one thing that you can do 462 00:16:09,150 --> 00:16:10,110 if you're not really sure 463 00:16:10,110 --> 00:16:11,670 what the TypeScript code should look like, 464 00:16:11,670 --> 00:16:13,530 especially in more complex functions, 465 00:16:13,530 --> 00:16:16,260 is you can start by writing a lot of your code in JavaScript 466 00:16:16,260 --> 00:16:17,670 and then add the TypeScript in later 467 00:16:17,670 --> 00:16:18,840 if you're a little bit confused 468 00:16:18,840 --> 00:16:20,610 on what the TypeScript should look like. 469 00:16:20,610 --> 00:16:23,608 The JavaScript for this isn't too terribly complicated. 470 00:16:23,608 --> 00:16:25,710 So we're gonna create an object here, 471 00:16:25,710 --> 00:16:27,720 which by default is just gonna be an empty object, 472 00:16:27,720 --> 00:16:30,420 and then we want to return that object at the very end. 473 00:16:30,420 --> 00:16:31,260 Another way we could do this 474 00:16:31,260 --> 00:16:33,210 is with the reduce function as well. 475 00:16:33,210 --> 00:16:35,370 It's entirely up to you which way you wanna go. 476 00:16:35,370 --> 00:16:38,130 In our case, I'm just gonna stick with this object method. 477 00:16:38,130 --> 00:16:40,350 Now what we can do is we can loop through our array. 478 00:16:40,350 --> 00:16:42,930 So we can save for each element in our array. 479 00:16:42,930 --> 00:16:45,090 What I want to do is I know that this element 480 00:16:45,090 --> 00:16:47,310 is specifically going to be multiple parameters. 481 00:16:47,310 --> 00:16:49,320 The very first parameter is going to be my key, 482 00:16:49,320 --> 00:16:51,300 and the second is going to be my value. 483 00:16:51,300 --> 00:16:54,420 So I can say object at this specific key 484 00:16:54,420 --> 00:16:57,750 is going to be equal to that specific value, there we go, 485 00:16:57,750 --> 00:16:59,190 that's all I need to do in my forEach, 486 00:16:59,190 --> 00:17:01,770 and then I'm returning my object down here. 487 00:17:01,770 --> 00:17:04,290 Now I need to add types to make all of this work. 488 00:17:04,290 --> 00:17:06,240 Well, I know that this is going to be an array 489 00:17:06,240 --> 00:17:08,160 if I specify this as an any array, 490 00:17:08,160 --> 00:17:09,660 that at least gets me part of the way there, 491 00:17:09,660 --> 00:17:11,490 but I actually know that this is a tuple, 492 00:17:11,490 --> 00:17:14,190 it's going to be specifically a tuple array. 493 00:17:14,190 --> 00:17:15,840 So I have a tuple array here, 494 00:17:15,840 --> 00:17:17,790 where the first value is always gonna be a string 495 00:17:17,790 --> 00:17:19,560 'cause I need to have a string is my key 496 00:17:19,560 --> 00:17:21,750 and the second value I have set to any. 497 00:17:21,750 --> 00:17:24,450 So that's working really well, and here for my object, 498 00:17:24,450 --> 00:17:26,550 I can just define this as a type of any right now 499 00:17:26,550 --> 00:17:28,230 just to get rid of all those type errors. 500 00:17:28,230 --> 00:17:30,300 So that's one way that I like to take my code 501 00:17:30,300 --> 00:17:32,550 when it's JavaScript and converting it to TypeScript, 502 00:17:32,550 --> 00:17:34,170 throw in any anywhere I don't really know 503 00:17:34,170 --> 00:17:35,340 what the type is going to be, 504 00:17:35,340 --> 00:17:37,130 otherwise manually specify the type. 505 00:17:37,130 --> 00:17:39,480 So here my array is essentially a tuple array 506 00:17:39,480 --> 00:17:41,123 where I know the very first value is a string 507 00:17:41,123 --> 00:17:43,440 and the second value I'm not really sure 508 00:17:43,440 --> 00:17:44,760 what it's supposed to be. 509 00:17:44,760 --> 00:17:46,380 That's a great use case for generics though 510 00:17:46,380 --> 00:17:48,570 because depending on what array I pass in, 511 00:17:48,570 --> 00:17:51,210 I know that this specific value is going to be different. 512 00:17:51,210 --> 00:17:52,260 So we'll just use the letter T 513 00:17:52,260 --> 00:17:54,660 to determine what this is going to be, there we go. 514 00:17:54,660 --> 00:17:56,730 Now I have this generic T type right here 515 00:17:56,730 --> 00:17:58,050 which is going to be what my value is, 516 00:17:58,050 --> 00:18:00,330 you can see it has that specific T type, 517 00:18:00,330 --> 00:18:02,880 and here my key has that specific string type, 518 00:18:02,880 --> 00:18:04,170 which is really great. 519 00:18:04,170 --> 00:18:05,910 Now for defining the type of my object, 520 00:18:05,910 --> 00:18:07,920 I can use that really fancy index syntax 521 00:18:07,920 --> 00:18:10,440 that I had from before, so instead of being an any object, 522 00:18:10,440 --> 00:18:12,480 this can be an object where the index here 523 00:18:12,480 --> 00:18:14,220 is specifically going to be a string. 524 00:18:14,220 --> 00:18:16,341 'cause I know that this is a string type right here 525 00:18:16,341 --> 00:18:18,330 and the value is going to be T. 526 00:18:18,330 --> 00:18:21,150 It's just gonna be one of these different T values. 527 00:18:21,150 --> 00:18:23,340 Now if I save that, you can see that this code right here 528 00:18:23,340 --> 00:18:24,720 is working fine and if we call it, 529 00:18:24,720 --> 00:18:26,190 it should also work as well. 530 00:18:26,190 --> 00:18:27,150 So let's just come down here, 531 00:18:27,150 --> 00:18:30,390 we're gonna say aToO pass in our array 532 00:18:30,390 --> 00:18:31,710 and we're gonna get the value, 533 00:18:31,710 --> 00:18:34,050 which is just our object, out the other end, 534 00:18:34,050 --> 00:18:35,640 and we can see that the type of our object 535 00:18:35,640 --> 00:18:36,627 is an index, which is a string, 536 00:18:36,627 --> 00:18:38,940 and a return value, which is a string, or a number, 537 00:18:38,940 --> 00:18:40,860 but it looks like we have a little bit of a problem going on 538 00:18:40,860 --> 00:18:43,200 with our actual array that's being passed in. 539 00:18:43,200 --> 00:18:45,270 The reason for that is actually because this array here 540 00:18:45,270 --> 00:18:47,400 should probably be typed as a tuple. 541 00:18:47,400 --> 00:18:48,690 So we can type it as a tuple 542 00:18:48,690 --> 00:18:50,033 where the first value here is a string 543 00:18:50,033 --> 00:18:53,370 and the second is either a number or a Boolean, 544 00:18:53,370 --> 00:18:54,630 just like that. 545 00:18:54,630 --> 00:18:56,231 And then if we make sure that this is an array, 546 00:18:56,231 --> 00:18:57,810 there we go, we can see we've gotten rid 547 00:18:57,810 --> 00:18:58,950 of all of our different errors 548 00:18:58,950 --> 00:19:00,180 and if we hover over this object, 549 00:19:00,180 --> 00:19:01,500 you can see that it has this type 550 00:19:01,500 --> 00:19:02,700 where the index is a string 551 00:19:02,700 --> 00:19:05,400 and the value is either going to be a number or a Boolean. 552 00:19:05,400 --> 00:19:08,940 So it's converted our array properly into this object type. 553 00:19:08,940 --> 00:19:10,800 Now I'm gonna really quick refresh what we did 554 00:19:10,800 --> 00:19:13,350 because this is actually fairly advanced TypeScript code. 555 00:19:13,350 --> 00:19:16,020 I guarantee in 99.9% of your days, 556 00:19:16,020 --> 00:19:18,420 you're not gonna write TypeScript code this complicated. 557 00:19:18,420 --> 00:19:20,070 But this is a great example of really trying to figure out 558 00:19:20,070 --> 00:19:21,780 how everything works, 'cause it combines together 559 00:19:21,780 --> 00:19:24,060 a bunch of the different things that we've talked about. 560 00:19:24,060 --> 00:19:25,140 The very first thing we did 561 00:19:25,140 --> 00:19:26,700 is we wrote it as a JavaScript function, 562 00:19:26,700 --> 00:19:27,900 since that's what we're familiar with 563 00:19:27,900 --> 00:19:29,580 and everything was working fine. 564 00:19:29,580 --> 00:19:31,140 Then we started adding in the types 565 00:19:31,140 --> 00:19:33,120 and we knew that the first value in our array 566 00:19:33,120 --> 00:19:34,380 is always gonna be a string 567 00:19:34,380 --> 00:19:36,270 just because that's how our object is set up, 568 00:19:36,270 --> 00:19:38,460 it always must have a key as a string, 569 00:19:38,460 --> 00:19:39,600 and then we know the second value 570 00:19:39,600 --> 00:19:40,890 can literally be anything at all, 571 00:19:40,890 --> 00:19:42,870 so we gave this a generic type of T. 572 00:19:42,870 --> 00:19:44,880 Since, depending on what arrays we pass in, 573 00:19:44,880 --> 00:19:46,634 we know we want this value to be different. 574 00:19:46,634 --> 00:19:49,110 Then we just specified this is our generic T, 575 00:19:49,110 --> 00:19:50,190 this is our generic T, 576 00:19:50,190 --> 00:19:52,470 and now for our actual return value of an object, 577 00:19:52,470 --> 00:19:54,510 we know we wanna take whatever the first value 578 00:19:54,510 --> 00:19:57,030 of the array is and use that as our index, 579 00:19:57,030 --> 00:19:58,710 that's why we wrote this code right here, 580 00:19:58,710 --> 00:20:00,600 and we know that the value of that is just going to be 581 00:20:00,600 --> 00:20:02,790 whatever the second value of our array is. 582 00:20:02,790 --> 00:20:05,640 That's why the value is set to that T variable here. 583 00:20:05,640 --> 00:20:07,260 The rest of this code is just plain JavaScript, 584 00:20:07,260 --> 00:20:08,190 there's no TypeScript at all, 585 00:20:08,190 --> 00:20:09,960 it just infers everything we need. 586 00:20:09,960 --> 00:20:11,220 Then down here just to make sure 587 00:20:11,220 --> 00:20:12,420 everything is linked up properly, 588 00:20:12,420 --> 00:20:13,560 we're essentially expecting this 589 00:20:13,560 --> 00:20:15,360 to be a tuple to be passed in, 590 00:20:15,360 --> 00:20:16,860 so we need to make sure that this array 591 00:20:16,860 --> 00:20:19,350 was also considered a tuple. 592 00:20:19,350 --> 00:20:21,540 Now, like I've said, this is a very complex 593 00:20:21,540 --> 00:20:23,730 bit of TypeScript code, so if you didn't quite understand 594 00:20:23,730 --> 00:20:25,830 exactly everything that was going on, that's perfectly okay. 595 00:20:25,830 --> 00:20:27,330 But this is a good showcase 596 00:20:27,330 --> 00:20:28,800 of pretty much the most advanced stuff 597 00:20:28,800 --> 00:20:31,200 that you're probably ever going to write using generics 598 00:20:31,200 --> 00:20:32,790 unless you're writing some really complex 599 00:20:32,790 --> 00:20:34,380 library style code. 600 00:20:34,380 --> 00:20:35,970 For the most part though, when you're using generics, 601 00:20:35,970 --> 00:20:38,220 it's gonna be something as simple as you know, 602 00:20:38,220 --> 00:20:42,240 document.querySelector, and you're gonna pass in 603 00:20:42,240 --> 00:20:44,370 that you want it to be an HTMLInputElement 604 00:20:44,370 --> 00:20:46,110 that you're getting from here instead. 605 00:20:46,110 --> 00:20:47,160 That's about as complex 606 00:20:47,160 --> 00:20:49,323 as most of your generics are going to get.