Advanced Patterns 11 exercises
Problem

The `as` Prop in React

For the next few exercises, we are going to look at different ways of handling the as prop in React.

Here we have a Wrapper component that has an as prop on it:


export const Wrapper = (props: any) => {
const Comp = props.as;
return <Comp {...(props as any)}></Comp>;
};

Loading exercise

Transcript

00:00 In this exercise and the next few exercises, we're going to be looking at the ASPROP. The ASPROP is probably the most complex TypeScript situation you can find yourself in in React. And so I want to prepare you, give you lots of different ways that you can tackle it, and also lots of different sort of difficulty levels as well.

00:17 Through the next few exercises, we're going to go from the kind of setting up of the problem all the way down to the most complicated and best setup for an ASPROP. So if you want to just like learn the best solution, then you can just click to the end. But there's plenty of good stuff sprinkled through here too. So what we have here is a wrapper component.

00:36 And this wrapper component has an ASPROP on it. And that ASPROP should be, first of all, auto-completing to everything that is a possible element in React. So div, span, a, all that stuff. And what it should do is when you specify that component, when you specify that AS thing, that's a required prop.

00:56 You've always got to pass it. What should happen is that the other props that you pass to that component should be the same props as the ones that you are supposed to pass to that component. So it does not exist, shouldn't exist, but an on-click pass to an as button should be inferred as a React mouse event HTML button element.

01:15 This is a tricky problem, but you do have all the tools that you need to solve it. We have jsx.intrinsicElements, which is a big global list of where you can basically get types for all of the elements that are supposed to be there. So div, span, a, all of those are on jsx.intrinsicElements.

01:34 We know about keyof, which is a way that you can extract the keys off that. We have as, which we will already be using down here. It's very confusing to refer to as here, but I mean assertions here. I'm pretty sure you're going to need this as any, but we'll see if you need it.

01:51 And then you have index access types too, which are a way of grabbing the type of that. I have found two solutions here. The first solution is based off an int, actually, and it doesn't use any, or doesn't turn this into a generic function.

02:06 I think this is the worst solution, but the second one uses a generic. So you can feel free to try to find both, but I will show you both afterwards. But I would, if you're just going to go for one of them, go for the generic type, because this is the kind of, I think the best one. And this turns wrapper into a generic function and does some manipulation there.

02:26 So good luck.