I have a simple polymorphic React component that is supposed to only render tag names (e.g. span) but not render custom React components (e.g. MyComponent). It looks like this can be achieved using JSX.IntrinsicElements. I have the following code:
import React from "react";
type PolymorphicComponentProps<T extends keyof JSX.IntrinsicElements> = {
as?: T;
} & JSX.IntrinsicElements[T];
const PolymorphicComponent = <T extends keyof JSX.IntrinsicElements = "div">({
as: Component = "div" as T,
...rest
}: PolymorphicComponentProps<T>) => {
return <Component {...rest} />; // TS error: JSX element type 'Component' does not have any construct or call signatures.
};
The generic type T will determine the HTML attributes that are available. For example, if I were to render PolymorphicComponent as an a tag...
<PolymorphicComponent as="a" />
...then I would get autocomplete for the href attribute/prop. And as another example, if I were to render PolymorphicComponent as an img tag...
<PolymorphicComponent as="img" />
...then I would get autocomplete for the src attribute/prop. This appears to be working as expected, but I am still dealing with the TypeScript error that is commented in the PolymorphicComponent component function definition: JSX element type 'Component' does not have any construct or call signatures.
What I can't figure out: The Component variable (alias for the as prop) has a type of T | (T & string). I would expect the type of Component to just be T.
If I create this very simple component that always renders a div, there are no TypeScript errors:
const DivComponent = () => {
const Div: keyof JSX.IntrinsicElements = "div";
return <Div />;
};
Question: What do I need to change in order to get rid of the TypeScript error? From what I've read, I don't need to replace the JSX with React.createElement so I'm looking to keep the JSX version of this component if possible.