Challenges 4 exercises
solution

Extract from String with Mapped Types, Template Literals, and infer.

Here's the solution I found:


type ExtractPathParams<TPath extends string> = {
[K in S.Split<TPath, "/">[number] as K extends `:${infer P}`
? P
: never]: string;
};

Let's break it down.

First, we have ExtractPathParams that takes in <TPath extends string>.

This says that

Loading solution

Transcript

0:00 This is the solution I found to this challenge. Let's break it down. First of all, we've got this ExtractPathParams type helper here, and we're taking in a parameter which is called Tpath. I'm going to start deleting this, and you're going to see that it starts breaking.

0:17 Let's just say type Result = ExtractPathParams, and let's say UserOrganizationPath, since that's the more complicated one. We can see that we end up with id and organizationId. Let's have a look at this extends string syntax first.

0:30 What happens if I delete that? Well, it looks like we've got an S.Split down here, which we saw earlier. This is saying this type parameter might need an extend string condition.

0:43 What this is doing is it's saying that we can only parse strings into our ExtractPathParams helper, so if we parse in a number here, then it's actually going to yell at us. We're going to cover this more in a future module, but you get the idea.

0:55 Now what we're doing is this very messy syntax here, if I clean this up a little bit, you can see that we're doing a map type here. Now the result, it looks like if I remove this, it looks like there's a K in something, and then there's an as here.

1:12 If I remove the as and the second little conditional here, then we actually end up with all of the members of this thing split up here. We've got an empty thing here, then users, then id, organizations, then organizationId

1:29 It looks like what's going on is we're splitting up the path and then taking all of the members of the path and then turning those into the keys. If I add this back in, let's break that down a little bit further.

1:42 If we say type Result2 equals this, and let's say, UserOrganizationPath, now what we get here, these are all of the members of this. If we remove the number too, it splits into an array, and by adding number on the end, we end up with all of the members of that array expressed as a union.

2:04 Now that we've got that, that's what K represents. K represents Result2 here. What we're then saying is we're remapping that to if K extends, infer P while we return P.

2:20 If it has a colon at the start, then we know that that's going to be a dynamic parameter, so it's going to be either id or organizationId, and we infer the rest of it during that check. Woah. Amazing use case for infer.

2:36 If we find it, if it matches one of these, then we return the parameter that we extracted, otherwise we return never. If we were to return wow inside here, then we'd always end up with this other parameter wow. Never basically says if it doesn't match this dynamic thing, then exclude it.

2:55 All of the values return a string, because that's how path parameters work basically. That's pretty amazing, and if we test this with UserPath instead, then we end up with just id string.

3:08 There are many, many different solutions to this possible problem, but hopefully, this one gives you a sense of how you could clean yours up or whether yours was correct. To be honest, if yours is working, then great job. This is a very, very difficult problem, and you managed to find a decent solution.

3:25 If you didn't manage to find a solution, then hopefully, this one gives you an idea about how you might tackle this in the future.