Say I have the following component:
interface Props {
as: keyof HTMLElementTagNameMap
// ... other props
}
const A = React.forwardRef<any, Props>((props, ref) => {
// ... implementation
})
This component will render an HTMl element based on the as prop, and the caller can pass in a ref to attach to the element. Currently, I'm using any for the type of the ref, but ideally, I'd want that to be the actual HTMLElement subtype based on the as prop that's being passed in. How can I do that? I can likely get the actual tag type from HTMLElementTagNameMap, but I'm just not sure how to write that into the function signature.
What you're asking is not possible (although there exists a workaround).
You need generics to "bind" together the two type parameters provided to forwardRef. Consider the following code:
interface Props<T extends keyof HTMLElementTagNameMap> {
as: T;
// ... other props
}
const A = React.forwardRef<HTMLElementTagNameMap[T], Props<T>>(
(props, ref) => {
return null;
}
);
The declaration of T parameter is missing at the component level. There is nowhere you can put such declaration. This is a limitation of React.forwardRef.
As a workaround, you can ditch forwardRef and add the ref to your Props interface:
interface Props<T extends keyof HTMLElementTagNameMap> {
as: T;
theRef: React.Ref<HTMLElementTagNameMap[T]>
// ... other props
}
function A<T extends keyof HTMLElementTagNameMap>(props: Props<T>) {
const { as, theRef, /*...*/ } = props;
return null;
}
Example in the TypeScript playground.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With