Check out a free preview of the full Making TypeScript Stick course:
The "Expert Type Challenges" Lesson is part of the full, Making TypeScript Stick course featured in this preview video. Here's what you'd learn in this lesson:

Mike walks through an example of an expert type challenge, including solving for the correct type for IndexOf<T, U>.

Get Unlimited Access Now

Transcript from the "Expert Type Challenges" Lesson

[00:00:00]
>> This last one is an attempt to implement index of. So you can see here, we've got a tupple with three numbers in it, 1, 2, 3. We wanna find out the position of 2 and it's starting counting it at 0. It is at the second or the first position, right?

[00:00:22] So here, index of 3, that's gonna give us 2. So it's 0,1, 2. And then just like index of with arrays, if it is never found, we should see at -1. So let's see if we can do that, just using type scripts, type information. This to me feels again like a recursive thing where we should effectively need to loop over this array, loop over this tupple.

[00:00:53] And the way to do that when you don't have a for loop is effectively to recurse or to use a map type. But in this case, we kinda wanna find the location of something and do something. So really, what we need is that looping mechanism, we can use recursion for that.

[00:01:12] And we need a condition where once met, we can evaluate out, right, we can start to count and then figure out. We can loop over and we can count, and then when we find we've met our condition, we can sort of return and then roll all the way back up, and evaluate out to that.

[00:01:35] And then all the way at the end if we reached the very end, we can sort of spit out -1 and say, hey, we never got there. So in order to do this, I'm gonna actually add a third type parameter, and this, who here is familiar with array.reduce.

[00:01:53] So we're gonna create something that's a lot like this accumulator, and we can use a type program for that. We're gonna call it Acc and we'll start it out as an empty array. So here we're gonna begin sort of our recursive loop. We can say, if, here let's say, T extends any, great.

[00:02:18] So we'll say, T extends F for first Rest, and we need to infer that and this. And so if we can match to that pattern where we can get a first thing and then everything else that's in the tupple, we're gonna say, How do I do that, we do it like this.

[00:02:54] IndexOf and then we're gonna pass in Rest. So that'll be, That'll be the remainder of the array. We're still looking for the same thing. Okay, so this is kind of our iteration pattern here and we'll terminate out to never for now. So let's just imagine this situation, we've got 1, 2, and 3, right, let's grab this.

[00:03:28] So when we do this infer, we're gonna have F = 1, and then Rest = [2, 3]. And then we're gonna call in to IndexOf. And we're searching for a 2 and then this is gonna be something like this. So here's why I'm doing this. If we keep effectively pushing elements just cuz we're changing this parameter here at the end, sorry, we don't wanna do this, something like that.

[00:04:09] Last element must be in the right time. Yeah, there we go. So let me make this a little more organized. So there's a thing to search through, a thing to search for, this is a kind of our accumulator. And we're gonna pluck off the first thing, we're gonna store the rest here, and then we're gonna effectively do this.

[00:04:33] This starts at empty, we're spreading it out, so that's adding nothing to this. And then here is the first thing that's this one that we plucked off. So this effectively, if we keep doing this, it'll kinda look like this. And at the point where we discover our condition is matched, we can look at the length of this tupple, this accumulator thing, and that will tell us effectively how many times we've gone through this loop.

[00:05:04] And if at some point, this shrinks down to nothing, the length is 0, now we know we've reached the end of the list, and we can spit out a -1. So now I'm feeling like we kinda have the tools in our toolbox that we need in order to make this work.

[00:05:25] So I'm actually gonna put this down here a little bit cuz I think the first thing we need to do after we pluck this off, is compare it. And, Just trying to think, we don't have a way of saying, look at the current index of this array. So let's do it this way, let's say, if T, Sub 0 extends U, then it met the length of this thing that we're summing up, right?

[00:06:12] So this would be, if this thing in the first position is exactly what we found, give me a 0, the zeroth position of the array. And then that's the end of it, otherwise, this is where we begin a search, this is where we begin the loop. Here's why it's important that I did this first.

[00:06:34] As soon as I pop off this first thing in the array, now my length has grown by one. And if this were regular JavaScript code, we'd say, no big deal, just return the length -1. What's the problem, -1 is a little bit hard in this environment here, right?

[00:06:51] Subtracting 1, it's actually, I'm not sure how we would go about doing that. So I'm making sure that we do this at the right point in time where that length is, what I want it to be already. So then if that fails, then we check to see if it matches this pattern effectively, we pluck off that first thing, and if that's true, then we omit that.

[00:07:21] Let me bring down another never. Actually this is just gonna evaluate, I'm gonna need something better than never to even just understand whether this is working or not. I see, we need a code in here. All right, awesome. Two test cases already passing, so this one works, it's only the case where we kind of like reach the end of the list and there's nothing left, that's where things kind of explode.

[00:07:59]
>> It could never just be -1?
>> Yeah, what about, we can just emit -1. Yeah, there you go, thanks.
>> [LAUGH]
>> All right, so I know this is why I wanna stop here, because this is super gnarly complicated stuff. Hopefully there is some value in listening to me think through this and break it down into smaller problems.

[00:08:26] And I think what you see me doing here, and this is something that you can do in your own TypeScript code, is peeling out sub parts of this type and building it up piece by piece by piece. I'm grabbing stuff here, I'm creating a variable like looking at the tooltip and you can see how I debug this kind of thing, that's the major struggle here.

[00:08:45] Because when things are messed up and you just see red squiggles everywhere. You do not have debugger, or a break point, or a console log, where you can sort of see what's going on with your system. All the more reason to practice with this kind of thing if you are using TypeScript at work.

[00:09:04] Because then your brain, and your knowledge of how things work, and the tools in your toolbox, that's how you can and rescue yourself. So again, type challenges, I strongly advise you, do one of these once in a while. A lot of the easy ones appear, quite easy, probably too easy for a lot of you.

[00:09:25] Spend some time in the medium area, right? Get used to it, they are hard, this is where the learning happens.