Member-only story
React polymorphic components with TypeScript

A polymorphic component is a popular React pattern. Even if you’ve never heard of it, you most likely encountered it in code. In a nutshell, the pattern lets you specify which HTML tag to use for rendering your component using as
prop.
The flexibility of the polymorphic component also makes it easy to misuse, and that’s where TypeScript can help us. Let’s see how we can use TypeScript and generics to write strongly typed polymorphic components.
Overview of polymorphic components
First, let’s see how you would use polymorphic components. Say you have a Button
component that you want to render as an HTML link. If Button
is a polymorphic component, you can write it like this:

Our button will render as a
tag and accept the same props a
tag accepts, like href
.
Simple implementation
Now let’s get to the implementation. Without type checking, the pattern is rudimentary to implement:

In our example above, we avoid any type checking by setting the component props type to any
.
Here is the line that makes our pattern work:
const Component = as || "button";
We render our component using the value of the as
prop or use the button
tag as a fallback. And that's all we need to make this implementation work.
The problem with this approach is that there is no mechanism to prevent the client from passing incorrect props:

We specified the href
property, which belongs to the a
tag, without setting our as
prop. Ideally, TypeScript would catch this bug immediately, and we would see an error.