The document discusses polymorphic components in React and TypeScript, explaining their complexity and use cases, particularly for component libraries or design systems. It walks through the creation of a text component that can render different HTML elements based on a prop, detailing the necessary TypeScript typings to ensure proper functionality and semantics. The tutorial emphasizes the importance of understanding this advanced concept, even if it's not frequently used.
The document discusses polymorphic components in React and TypeScript, explaining their complexity and use cases, particularly for component libraries or design systems. It walks through the creation of a text component that can render different HTML elements based on a prop, detailing the necessary TypeScript typings to ensure proper functionality and semantics. The tutorial emphasizes the importance of understanding this advanced concept, even if it's not frequently used.
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 4
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