https://v4.mui.com/guides/typescript/#usage-of-component-prop shows this example of a generic custom component wrapping Typography
:
function GenericCustomComponent<C extends React.ElementType>(
props: TypographyProps<C, { component?: C }>,
) {
/* ... */
}
which makes props of the component
prop available in GenericCustomComponent
:
function ThirdPartyComponent({ prop1 } : { prop1: string }) {
return <div />
}
// ...
<GenericCustomComponent component={ThirdPartyComponent} prop1="some value" />;
This works fine.
However, in my case some wrapper components are defined using forwardRef
. Simplified:
import { Link, LinkProps } from '@material-ui/core'
export const CustomLink = forwardRef<HTMLAnchorElement, LinkProps>(({ children, ...muiProps }, ref) => {
return (
<Link ref={ref} {...muiProps}>
{children}
</Link>
)
})
and the type of CustomLink
is
React.ForwardRefExoticComponent<Pick<LinkProps<"a", {}>, ...> & React.RefAttributes<...>>
Is it possible to make CustomLink
generic similarly to GenericCustomComponent
, so its type will be something like
<C extends React.ElementType = "a"> React.ForwardRefExoticComponent<Pick<LinkProps<C, { component?: C }>, ...> & React.RefAttributes<...>>
I don't believe the above type is actually legal in TypeScript, but the intention should hopefully be clear.
This is the version I ended up with which seems to work in the initial testing:
import { Link, LinkProps } from '@material-ui/core'
interface LinkType {
<C extends React.ElementType = 'a'>(props: LinkProps<C> & { component?: C }): React.ReactElement
defaultProps?: Partial<LinkProps>
displayName?: string
}
// eslint-disable-next-line react/display-name -- false positive
export const CustomLink = forwardRef<HTMLAnchorElement, LinkProps>((props, ref) => {
const { children, ...muiProps } = props
return (
<Link ref={ref} {...muiProps}>
{children}
</Link>
)
}) as LinkType
but I wasn't able to make it generic to avoid duplication for multiple components. Any improvements welcome.