Use infer with Generics to Extract Types from Arguments
Before we get to the solution, let's take a look at another example.
Here Example2
is calling GetPoint
on MyComplexInterface
, and we're trying to return the 4
:
type Example2 = GetPoint<MyComplexInterface<l, 2, 3, 4>>;
For a first pass at a solution for GetPoint
, we call `MyC
Transcript
0:00 Let's take a look at the solution here. I've got an Example2 here, which is going to call GetPoint on MyComplexInterface, and we're trying to return this 4 here. As you'll see, it's currently hovering over any.
0:15 What's going on here is that, inside the GetPoint function itself, what we're doing is saying T extends MyComplexInterface, and we're passing any into each of the slots. If we don't pass any of these, then it's going to yell at us because it requires four type arguments.
0:29 What we can do is we now know that T extends that thing. If I try to pass in something random like 1-2-blah-blah-blah, then I'm going to get never because it's going to hit that branch there instead of this branch. What we need to do is somehow, inside here, use an infer to extract out one of the slots.
0:51 One thing we could do is say T, let's say getPoint, return type getPoint. That makes our tests pass. We end up with the 4 here that we're passing in. If I change that to 12, then we get 12, but it sort of ties the conditional type to the internal structure of this interface here, which might not be something that we always want to do.
1:16 We want to look at the public declaration of that interface, which is the type arguments, which are pretty unlikely to change, or less likely to change let's say. Inside here, what we can do is let's say any for now. We can add an infer to any one of these slots here. Let's say we infer TPoint here. We can then just return TPoint.
1:42 Now, you get all the benefits of being able to extract out all the members of the type arguments without needing to dive deep into the element itself and understand its structure. We can even do more of this. We can say infer -- what's that one -- if infect TEvent, infer TContext, and then infer T whatever. What you end up with is a bunch of different infers.
2:12 This has no behavioral difference. I'm just showing you that you can infer multiple slots if you want to. We can return the TContext if we want to or the TEvent or something. Having them as any is also fine because all we really care about in this case is extracting the TPoint. This is another really cool use case of infer because you can just extract out the type arguments to another type helper.