Reputation: 873
Not sure if the name "generic component" is correct, nonetheless I cannot come up with the right way of doing that.
The idea is to have a component that accepts tag
as a prop, and that tag
can be either a string (tag name) or a component constructor (FC, class component).
Here's the example code of what I'm trying to achieve
export const MyComponent = () => {
return (
<GeneicComponent tag="span">
{/* some content here */}
</GeneicComponent>
)
}
export const MyComponent2 = () => {
return (
<GeneicComponent tag={SomeCustomComponent} {/* SomeCustomComponents props */}>
{/* some content here */}
</GeneicComponent>
)
}
This approach works just fine until you're trying to pass extra props. GenericComponent must infer those props from tag
and extend its own props with inferred ones, yet I have no idea now how to do that. Another problem is to infer props when the tag name passed as a string. I'm pretty sure it's something related to JSX.IntrinsicElements
but had no luck experimenting with that.
Appreciate any suggestions.
Upvotes: 1
Views: 402
Reputation: 138267
The component is just a function and it's props are just the first parameter to that function. One can derive the parameter type from a function type:
function GenericComponent<T extends Function>(
props: { tag: T } & { [key in keyof Parameters<T>[0]]: Parameters<T>[0][key] }
) { /*...*/ }
Upvotes: 2