React and TypeScript

React and TypeScript Polymorphic Components Solution

This course has been updated! We now recommend you take the React and TypeScript, v2 course.

Check out a free preview of the full React and TypeScript course:
The "Polymorphic Components Solution" Lesson is part of the full, React and TypeScript course featured in this preview video. Here's what you'd learn in this lesson:

Steve live codes the solution to the Polymorphic Components exercise

Get Unlimited Access Now

Transcript from the "Polymorphic Components Solution" Lesson

>> All right, so like most of our exercise that we're gonna kind of redo part of it and then we're throwing a little extension cuz why not? All right, so let's think about all the things that we did last time. We had this as property here. And again it's optional cuz we'll default to a div, we're cool with it.

[00:00:15] You don't wanna give me an as? I don't insist on having an as, but if you can give me an as, it's going to be this element generic. Again, we use E or T cuz that's the convention. You wanna use sandwich as your generic, use sandwich, that's between you and your teammates.

[00:00:30] And if it gets past code review, that's fine. So we have E and that has to that, we want to insist that like, if we're gonna try this, it's gonna fall to an HTML element. And get all the benefits of that, allowing the different props that HTML element takes.

[00:00:47] We need to again TypeScript just wants to help, it helps you. So and will default down to a just the base element type if we can't set that. All right, so we've got that in place. And all right, so now, this is really text on props because it's again the special ones that we have and again, that's just a convention.

[00:01:13] So then really the ones that we're gonna use with our actual text component is the combination of these props and whatever is on the underlying HTML element. So here, we've got text props extends react.element type. And that is going to be everything and text own props. Around that element type, and then omit.

[00:01:47] Everything that's in the HTML element. Omit everything, take everything as HTML element, omit the things that are in text own props, and then fill in our text own props. So it's basically a way to override anything that we might be stepping over. In this case, we're stepping over children.

[00:02:02] That, yeah, so well you have omit react.component props. And it's gonna be again, whatever E is in this case, so get all the props of that element and then take out everything in text on props. All right, so we've got our two types in place. Now you can see this is angry with us again, cuz it's now expecting a generic and we didn't give it a generic.

[00:02:38] We can handle that. We've decided for whatever decision making process that we have, that we've got default element, that's gonna be a div. Cool, and now we're gonna say cool. So these text props is expecting some kind of definition here. And again, we're just saying that with this component, cool, yeah, we want something that is gonna be react that on the type.

[00:03:07] And we'll let it default in this case that is going to be whatever our default element is. In this case, that's a div and we'll close that angle bracket. It's angry cuz bullying is not assignable text prompts any. Do with that a moment, let's finished something and we'll debug in a second.

[00:03:28] So we've got all of that there. All right, now we need to do a little bit of refactoring here And we know that we're gonna have this idea or we have as now as well. And we're gonna say that we've got as, and we're gonna say const tagname is going to be either whatever we passed in as.

[00:03:59] In this case, it's a div by default, otherwise, it's going to be whatever we pass in. And we're here, we'll say tag name. All right, so we've got all of that in place. So we'll do one more other thing in a second. Boys outside will text prompts any, let's see react at all in type.

[00:04:40] And clear. I feel like I made a little syntax error here since my highlighting goes away after a certain point. So let's see. Syntax I think came back. So there's definitely some error there, let's say children. All right, element type. This is a regular function so it goes on this side here.

[00:06:02] I was using the arrow function syntax, but this one is a regular function. All right, everything's good at this point. There's still some upset meant here. Let's see, its value's never read. That is true, As well. All right, so we've got that in place. Now everything works. And you can see I can say this is as, say there's a label.

[00:06:47] Make sure that actually, all right, so as works correctly and then we say HTML for id. And that works with that but if I make it a div again, it doesn't work again. One other thing that we can do is that htmlFor. So the question is anyway, catch the error on TypeScript when passing in an avoid element like HR.

[00:07:10] I don't know, off the top of my head, let's actually play around with it for a second. Because this won't accept children in this case, but seems like I can't catch it. There's some thickness around, like there are limitations to some of this. Like you can specify like components that match a certain property.

[00:07:29] You can't say that like, okay, we're gonna render only a certain type of component, so on and so forth. So I don't know the answer to that one off the top of my head. But we can see we've got some of that in place. The interesting part is right now, we'll accept all of these, but we kind of eat them.

[00:07:47] Like we can pass an htmlFor because it never makes it to the tag name at all. So one of things we can do since there are additional properties, is we can kind of grab a rest prop. We could say, rest and pass in everything else along these lines.

[00:08:10] So here we say label, and everything else that's passed through, we'll get pass through to that tag name that we're using. Yeah, in this case, it's the label before it was a div. And, yeah, well, that's like how do we know because TypeScript knows. TypeScript's not gonna let anything in that the underlying element that we're wrapping doesn't accept, right?

[00:08:31] So we get all of that safety, but we still get to have these very like nuanced and adaptable components as well.