Passing Type Arguments with Lodash
The solution is based on understanding the groupBy
function, so we'll start by looking there.
interface LoDashStatic {
/**
* Creates an object composed of keys generated from the results of running each element of collection through
* iteratee. The corresponding value of
Transcript
0:01 The solution here then is based on the idea that we need to understand this groupBy function. Let's dive into it. We can see that groupBy takes in a collection of a list, T, or , or undefined. That's interesting. Let's investigate what a list is. A list is an ArrayLike<T. It's just an alias that Lodash uses.
0:24 It looks like there's quite a lot of aliases that it uses. An ArrayLike comes from lib.es5.d.ts. It's basically just something with a length and something with end number T. What this means is that list is just a alias for array. It's an array of something or , or undefined. Itinerary is the age that we're passing in.
0:53 Value itinerary, it looks like it can either be a value T or not void, interesting, or itinerary shorthand. Value T equals not void. Again, this is another alias that we're having to dive into. This is the value that is in our array that we pass or sending to not void, unknown. That's less useful than just unknown, surely.
1:18 Value itinerary, and then itinerary shorthand. Itinerary shorthand is property name. String or number, or symbol, another alias, or a tuple with property name and any, or a partial shallow T. This is then P in key of T. We're getting in the weeds here because it looks like you can just pass in itinerary shorthand, property name, string, or number, or symbol.
1:48 That's what we're doing with this age thing. It looks like we're not getting any inference from this. It's just saying, "We get this. We just pass in the string." Then it returns a dictionary. This dictionary, if we Command-click, this is an object with an index on it. This index is the same as if we were to say type dictionary equals record string T.
2:16 This is just an index signature on this. A dictionary then is like a record. We understand that a list is an array. In lodash terms, a dictionary is a record. Then it looks like there's another function overload here. This is when T extends object. Instead of passing a list here, you're passing in T. It's an object itself.
2:37 There's some complicated stuff there where it looks like it's a dictionary with an array -- T key of T. Confusing. What we're interested in is this overload. We're not interested in this one down here because we have an array of something that we're passing in and it looks like this T is the thing we care about.
2:57 This T means that groupBy actually takes in a type argument. That's what's going to be pushed into this value here. Let's put in this T in the groupBy. Now, this array of unknown, we know that this is going to be T, too, because whatever we pass in here gets passed in via array here. Except, T is undefined. It cannot find names.
3:19 We're going to add it onto here. This now will start working. We're going to get groupBy T. It takes an array, which is an array of T, which might as well be, we could call this list T as well, which we get from lodash. This is underscore list T. Then we pass it into groupBy. Then we get back dictionary T array.
3:46 What we have, result is now name and age wrapped into a dictionary. If I were to add ID -- 12...blah, blah, then this is going to get added there, too. Super-duper nice. There's one more test that we're not passing here, which was we're not passing this case where we have to pass in age into here.
4:07 This is pretty simple. All we need to do is just extends age number here. We just add a constraint into the generic to make sure that we can pass it in. This is actually something that lodash itself doesn't need. It's part of the test suite down here. We should add it there.
4:25 This should give you an idea of how to break down different functions that come from external libraries, how to look at the generics they need, and how to use their nomenclature using list and using dictionary in order to understand how the generics flow. There's one more cool thing here, which we don't need to pass in the type argument manually.
4:46 We can actually remove this, and groupBy, it understands that this is a list of T. If we look at this, T can be anything. T can be anything here as long as we pass it in a list. What happens here then is because T can be anything here, it's actually more constrained on the outside than the inside. Then it just infers it into here. Then we still get back dictionary T array.