Advanced Patterns 11 exercises

Infer Shared Props for Multiple Components

Our goal is to have the COMPONENTS correspond to a certain type and have their props inferred without manually typing them.

Let's look at a couple of approaches to solving this problem.

The first thing we'll do is make COMPONENTS into a Record where the keys are string and the values are

Loading solution


00:00 So there is a pretty simple way that we can get this working. We want to make sure that components is like it corresponds to a certain type. We want to make these props kind of inferred from something and not have to type them all manually. So the obvious type that comes to mind is to basically say we have a record here

00:19 where the record is string and all the keys are string and the values of that record is a function. So we can use actually react.fc in this position quite nicely. So react.fc with input props as the props and now props is all inferred beautifully.

00:36 Now let's go down to input down here and see if we can figure out this props type. Well these props we need to have a type here and probably we need to say okay type is going to be keyof typeof components which we've also seen as a pattern before.

00:54 So keyof typeof components and we also want to be able to pass in the rest of the props here. So these props are going to be and input props. Okay so this is all looking pretty good now. We've got our types all working except though that type is being inferred as string here

01:11 not the individual elements of our components here. Well why is that? Well it's because our record here is actually overriding the type. It's not inferring that text number and password are here. It's only seeing that this is a record of strings here. Now we can get this working.

01:28 We can say type input equals text or let's say number or password and then we can replace this with this. So I shouldn't use this. I should say input type let's say. So input type I stick that there and now we're getting proper errors.

01:46 So this type email here is erring and now we've got type number password text beautiful and that's going to render out the proper components because props.type is kind of like assignable or you can use it to index into there. But this isn't quite as satisfying as we want it to be satisfying.

02:06 And that was totally unintentional but very very useful for where we're going. This input type we've got a bit of duplicated stuff here. Text is duplicated, number is duplicated and password is duplicated. Wouldn't it be good if instead of just like having to assign this

02:21 we could make sure that the component stuff actually satisfies the criteria that we've set out and then just let it infer what it wants to infer. Well in the second solution here we can use satisfies using satisfies record string react.component type input props. I'll change this to react.fc just for clarity.

02:41 So this is great. Now components if we see we still don't need to type these props because TypeScript actually picks up that we want to infer it as input props here. Very very clever of it. And if we don't have this here then it has no clue what these props are supposed to be

02:58 and it's going to implicitly turn it into an any type. But we no longer need to have the thing that we had here before. So we no longer need to do input type. In fact let me just refactor this so it matches up. We say satisfies this. We can say satisfies record string. Now everything just works.

03:16 So key of type of components is no longer just string. It's actually number, text, and password. Beautiful. So this is a really really nice pattern if you want to kind of build these kind of slightly polymorphic components that always take the same props. Really nice.