Challenges 4 exercises

Create an Object using Mapped Types, Conditional Types, and TypeScript Keywords

Here's what my solution looks like:

type RoutesObject = {
[R in Route as R["route"]]: R extends { search: infer S } ? S : never;

As usual, we'll break it down bit by bit.

Turn the Discriminated Union into an Object

The first thing to do is turn the discriminated union into an

Loading solution


0:01 We know first of all that to take a discriminated union and turn it into object, it's pretty nice. We get to use this R in Route as R route, which we've seen before. If we just take this R now, and if we take R route's objects, we now have each of the members of this discriminated union mapped over into its own key. Very cool.

0:22 That's good, because actually, what we want is to turn it into an object with those keys. This section is done for us. We don't need to think about that anymore. The tricky bit is this next section, because all we want from this routes object is actually to turn this, we want to basically grab the search out of it.

0:42 We have our R here, and R can contain search or it might not contain search. We can't just do this, because R might not contain search at all times. R is going to be basically like one of these. Some of these contain search, some of them don't.

1:01 You can't do a partial on this, or I can't do an index access on something that might not be there. We need to go in using a conditional type and grab it.

1:12 What we're going to do is we could say R extends search any and then say R search, otherwise return never. That actually works and it works pretty well. You can see that it grabs all the pieces here, but I like doing it like this, which is to say infer S.

1:30 Infer S in this position basically does the same thing except it does it without the index access check. It just says if this matches the search then grab it and then return it, which I think is just cleaner than looking at that and having to work out what that any is for.

1:45 If that any is typed to something different, although unknown does work, undefined or something, then it's not going to work. I prefer using the infer S, because it just looks a little bit cleaner, and you get to understand exactly what this check is doing.

2:02 Now this works, and this little check is so useful for being able to extract things that you're not sure are they in all members of the union.