React TypeScript Tutorial – 24 – Polymorphic Components
Video Title: React TypeScript Tutorial – 24 – Polymorphic Components
Welcome back everyone for the last topic in this series we’re going to take a look at polymorphic components with react and typescript it is probably one of the more complex concepts to understand as a beginner but hopefully i can do a good job of breaking it down for you
It is something you don’t need unless you’re building a component library or a design system for your project at work having said that it never hurts to know how it works irrespective of whether you’ll be using it or not let’s begin for this example within the components folder i’ve created a folder called
Polymorphic within this folder i’ve created a file test.tsx the file contains a simple text component let me walk you through the code first we have the component props type the text component will accept three props optional size which can be small medium or large optional color which can be primary or secondary
And finally children in the component we have one div tag and the assumption is that size and color are used to calculate the styles for the div tag the children prop is rendered in the browser in app.esx we can invoke the text component passing in the different props
Text component size is equal to large and the text is heading size is equal to medium the children text is paragraph size is equal to small color is equal to secondary and the text children is label now this would work but there is one problem although i have one reusable component
To render either a heading or a paragraph or a label the underlying html element is the same a div tag and this for sure is not good for semantics what we should be able to do is pass in another prop which controls what html element is rendered in the browser for example
On the first text component as is equal to h1 on the second as is equal to paragraph and for the third one as is equal to label we want this text component to behave like different html elements based on this as prop such a component is called a polymorphic
Component and in this video we’re going to learn how to type that component let’s go over this one step at a time our step one is obvious we need an ass prop which controls what is the element rendered in the browser i’m going to start with as this is optional
And the type is string that fixes the error in app.tsx in our component we can now destructure it and use it instead of the div tag so children comma as and within the component const component is equal to the as prop or we default it to a div tag
This defaulting is because as is an optional prop now instead of the div tag we specify component that completes our step one but obviously typescript is not happy it’s complaining about the component type and i’m sure you would have guessed as well that the prop cannot be any random string
So for step two let’s fix this type of the as prop we know it has to be a valid html element but what is the type well the correct type is react dot element type if you now go back to app.esx and clear out is equal to h1
And i type is equal to quotes you can see the intellisense working already i can now select h1 so we are making progress let’s now move on to step three at the moment we are asking text component to render as h1 or a paragraph or as a label
But the component is not capable of handling the html element props for example a label will typically have a for attribute if i were to add html4 is equal to some id typescript throws an error let’s fix this we’re going to begin by changing text props to text own props
And this is a common convention for this type of a scenario we then define the text props type as a combination of text owned props along with the html props it is supposed to accept so type text props is equal to text own props and then it should also include react dot component
Props but react dot component props is a generic type we actually need to figure out what is the html element whose props need to be combined with text own props but if you think about it the html element passed as the ask prop could be anything
So what we need is a generic element type and we begin with text own props we pass in a generic type e which extends react dot element type and then instead of react.element type for the as prop we specify e next we do the same for text props as well
We add a generic type e extends react dot element type and for text own props we pass in the same e and also for react dot component props but when we do this there is room for name collision and duplicate types for example children might collide with children for a div tag
So we need to omit the keys that are specified as part of text own props and we do that using the omit utility type so right before react dot component props we add omit angle brackets and this would be sort of the first argument we then put a comma and then key off
Text own props we also need to pass in the generic so we now have all the types of this element except for the types that we have specified ourselves now on line 13 for our text component itself we need to add the generic type so export const text and before parentheses angle brackets
E extends react dot element type we assign a default element which is the div tag we pass in the same generic element e to text props and when we do that the typescript error for html4 prop is gone typescript is happy again if you were to specify
Html4 on an h1 text component though typescript throws an error because html4 is not valid for an h1 tag that completes our polymorphic component if you were to take a look at the browser you can see the text components have been rendered as an h1 tag a paragraph tag and a label tag
All this without typescript throwing an error like i mentioned earlier typing polymorphic components is pretty advanced and not something you would need on a regular basis but it’s always good to know there is a resource available for you and you can come back to this should a need arise in
The project you’re working on alright thank you all for watching and i’ll see you in the next video
-
Sale!
Wireless WIFI Repeater Extender Amplifier Booster 300Mbps
$29.99$14.99 Add to cartWireless WIFI Repeater Extender Amplifier Booster 300Mbps
Categories: Electronics, Wi-Fi Router, Wireless Wi-Fi Extender Tags: 300Mbps, 802.11N, Amplifier, Booster, Extender, mobile wi-fi booster, Remote, WIFI, Wireless, Wireless WIFI, Wireless WIFI Repeater, Wireless WIFI Repeater Extender, Wireless WIFI Repeater Extender Amplifier, Wireless WIFI Repeater Extender Amplifier Booster, Wireless WIFI Repeater Extender Amplifier Booster 300Mbps$29.99$14.99 -
Sale!
Full RGB Light Design Gaming Headset Headphones with Mic
$24.99$14.99 Add to cartFull RGB Light Design Gaming Headset Headphones with Mic
Categories: Electronics, Gaming, Gaming Headsets Tags: Design, Full, Full RGB Light Design Gaming Headset, Full RGB Light Design Gaming Headset Headphones, Full RGB Light Design Gaming Headset Headphones with Mic, Gamer, Gaming, Gaming Headset Headphones, gaming headset wireless, Headphone, Headphones, Headset, Light, Mic, Package, RGB$24.99$14.99 -
Sale!
Wireless BlueTooth Multi-Device Keyboard Mouse Combo
$39.99$19.99 Add to cartWireless BlueTooth Multi-Device Keyboard Mouse Combo
Categories: Electronics, Gaming, Gaming Keyboards, Keyboard Mouse Combos Tags: Combo, Keyboard, keyboard mouse combos, Mouse, MultiDevice, Set, WireKeyboard Mouse Combo, Wireless, Wireless BlueTooth Keyboard Mouse Combo, Wireless BlueTooth Keyboard Mouse Combos, Wireless BlueTooth Multi-Device Keyboard Mouse Combo, Wireless BlueTooth Multi-Device Keyboard Mouse Combos$39.99$19.99 -
Sale!
High Back Leather Executive Adjustable Swivel Gaming Chair with Headrest and Lumbar
$199.99$139.99 Add to cartHigh Back Leather Executive Adjustable Swivel Gaming Chair with Headrest and Lumbar
Categories: Gaming, Gaming Chairs Tags: Adjustable, Chair, computer chairs, Desk, Executive, Gaming, Girl, Headrest, High, High Back Leather Executive Adjustable Swivel Gaming Chair, High Back Leather Executive Adjustable Swivel Gaming Chair with Headrest, High Back Leather Executive Adjustable Swivel Gaming Chair with Headrest and Lumbar, High Back Leather Executive Adjustable Swivel Gaming Chairs, Leather, Lumbar, Office, Racing, Swivel$199.99$139.99 -
Sale!
Professional LED Light Wired Gaming Headphones with Noise Cancelling Microphone
$29.99$19.99 Select optionsProfessional LED Light Wired Gaming Headphones with Noise Cancelling Microphone
SKU: N/A Categories: Electronics, Gaming, Gaming Headsets Tags: Cancelling, Gaming, Gaming Headphones with Noise Cancelling Microphone, gaming headset, Headphones, Headset, LED, Light, Mic, Microphone, Noise, Professional, Professional LED Light Wired Gaming Headphones, Professional LED Light Wired Gaming Headphones with Noise Cancelling Microphone, Wired, Wired Gaming Headphones, Wired Gaming Headphones with Noise Cancelling Microphone$29.99$19.99 -
Sale!
Gaming Desk with LED Lights USB Power Outlets and Charging Ports
$349.99$249.99 Select optionsGaming Desk with LED Lights USB Power Outlets and Charging Ports
SKU: N/A Categories: Computer Desk, Gaming, Gaming Desk Tags: and Charging Ports, Charging, Desk, Desks, Gaming, gaming desk with led lights, Gaming Desks with LED Lights, Home, LED, Lights, Monitor, Office, Outlets, Port, Power, Room, Stand, USB, USB Power Outlets, White, Workstation$349.99$249.99 -
Sale!
Wired Mixed Backlit Anti-Ghosting Gaming Keyboard
$99.99$79.99 Add to cartWired Mixed Backlit Anti-Ghosting Gaming Keyboard
Categories: Electronics, Gaming, Gaming Keyboards Tags: Antighosting, Backlit, Blue, brown, Gaming, Gaming Keyboard, gaming keyboards, gaming keyboards and mouse, Keyboard, Laptop, Switch, Wired, Wired Mixed Backlit Anti-Ghosting Gaming Keyboard, Wired Mixed Backlit Anti-Ghosting Gaming Keyboards, Wired Mixed Backlit Gaming Keyboard$99.99$79.99 -
Sale!
Wireless Bluetooth 5.3 ANC Noise Cancellation Hi-Res Over the Ear Headphones Headset
$119.99$59.99 Add to cartWireless Bluetooth 5.3 ANC Noise Cancellation Hi-Res Over the Ear Headphones Headset
Categories: Electronics, Gaming, Gaming Headsets Tags: 5.3 ANC Noise Cancellation Hi-Res Over the Ear Headphones Headset, ANC, Audio, Bluetooth, Cancellation, Ear, Earphone, gaming headset, Headphones, Headset, Hi-Res Over the Ear Headphones Headset, HiRes, Noise, Wireless, Wireless Bluetooth 5.3 ANC Noise Cancellation Hi-Res Headphones, Wireless Bluetooth 5.3 ANC Noise Cancellation Hi-Res Over the Ear Headphones Headset, Wireless Bluetooth 5.3 ANC Noise Cancellation Hi-Res Over the Ear Headphones Headsets$119.99$59.99 -
Sale!
Wired Sports Gaming Headset Earbuds with Microphone
$19.99$9.99 Select optionsWired Sports Gaming Headset Earbuds with Microphone
SKU: N/A Categories: Gaming, Gaming Headsets Tags: Accessories, Earbud, Earphone, Earphones, Gaming, gaming headset with microphone, Headphones, Headset, IOS, Microphone, Sports, Wired, Wired Sports Gaming Headset Earbuds, Wired Sports Gaming Headset Earbuds with Microphone, Wired Sports Headset Earbuds$19.99$9.99 -
Sale!
150W Universal Multi USB Fast Charger 16 Port MAX Charging Station
$49.99$29.99 Add to cart150W Universal Multi USB Fast Charger 16 Port MAX Charging Station
Categories: Charging Stations, Electronics Tags: 150W, 150W Charging Station, 150W Universal Multi USB Charging Station, 150W Universal Multi USB Fast Charger 16 Port MAX Charging Station, 150W Universal Multi USB Fast Charger 16 Port MAX Charging Stations, 150W Universal Multi USB MAX Charging Station, 16 Port MAX Charging Station, 3.5A, Charger, Charging, Fast, laptop charging stations, Max, Multi, Port, Stand, Station, Universal, USB$49.99$29.99
Use coupon code CodevolutionYoutube for 100% off lifetime discount to your subscription at https://www.taskade.com/billing
Thank you So much
You are a great Teacher🙏
awesome typescript tutorials thank you
Thank you for the tutorial
nice video,thanks… but you forgot something: you should destructure a …rest prop like you did in a previous video and pass it to the Component because now if you add for example a htmlFor attribute typescript doesn't throw an error but the functionality for a label doesn't work.
GoodJob!
TS is happy again but maybe JS is ever happy
This playlist helped me a lot a few months back when I started at a new company using React + Typescript. Thank you so much
damn… i don't even know you could do this in plain js! i just start learning react 🙂
TypeScript Section ok, but click event not working:
// components/button.tsx
type MyComponentOwnProps<E> = {
children?: React.ReactNode
component?: E
}
// type MyComponentProps<E extends React.ElementType> = MyComponentOwnProps<E> & React.ComponentProps<E>
type MyComponentProps<E extends React.ElementType> = MyComponentOwnProps<E> &
Omit< React.ComponentProps<E>, keyof MyComponentOwnProps<E> >
const MyComponent = <E extends React.ElementType = 'div'> ({ children, component }: MyComponentProps<E> ) => {
const Component = component || 'div'
return (
<>
<Component>{children}</Component>
</>
)
}
export default MyComponent
// /pages/index.tsx
import MyComponent from '../components/button'
const Home = () => {
return (
<>
<MyComponent component='button' onClick={console.log} >Hello Button </MyComponent>
<button onClick={console.log}>Button</button>
</>
)
}
export default Home
Very very strong tutorials please continue more and advanced tutorials like these .. thank you
Thanks alot man for the series. Very helpful !!!!!
amazin
After 3rd time I completely understood…but you are awesome brother..
damn this one was hard to take…
Nice, but what if need access to ref? I mean forwardRef polymorphic component.
Type '{ children: ReactNode; className: string; }' is not assignable to type 'LibraryManagedAttributes<E, any>' Getting this error please help
\
a bit hard..
this one is little difficult to understand 🙂 – regarding the name collision. Thanks for bringing up this tutorials, they are very helpful
I have to say that this is the hardest one to keep up with because it combines much of what we have already learned implemented in a complex manner. Thank You, for sharing this with such a detailed example…
Thanks!
Thank you