Explaining my difficult, I already tried to find a solution, but or I don't know exactly the term to search, or don't have any answer.
What I would like to do is create a ButtonBase
element like React Material UI does. I want a component that will render by default a button, but if I give a param component="a"
it will render inside a <a>
tag. This way I can use the styled components to style only once any button.
So, I created this component:
import React from 'react'export type ButtonBaseProps = | ({ component?: 'a' } & React.AnchorHTMLAttributes<HTMLAnchorElement>) | ({ component?: 'button' } & React.ButtonHTMLAttributes<HTMLButtonElement>)const ButtonBase: React.FC<ButtonBaseProps> = ({ component: Component = 'button', ...rest}) => { return <Component {...rest} />}export default ButtonBase
Explaining the code:
- I created ButtonBaseProps that will tell that I'm receiving a
<a>
element with any anchor related props, OR I'm receiving a<button>
with the button related props.
That works fine anywhere I use. If I type <ButtonBase component="a" href="/">Link</Button>
will work, and if I type <ButtonBase component="button" href="/">Button</ButtonBase>
will throw an error, because property href
doesn't exists in an anchor.
The fatal error happens in the component rendering <Component {...rest} />
:
Type '{ download?: any; href?: string; hrefLang?: string; media?: string; ping?: string; rel?: string; target?: string; type?: string; referrerPolicy?: string; defaultChecked?: boolean; defaultValue?: string | number | string[]; ... 251 more ...; onTransitionEndCapture?: (event: TransitionEvent<...>) => void; } | { ...; }' is not assignable to type 'IntrinsicAttributes & ClassAttributes<HTMLAnchorElement> & AnchorHTMLAttributes<HTMLAnchorElement> & ClassAttributes<...> & ButtonHTMLAttributes<...>'. Type '{ download?: any; href?: string; hrefLang?: string; media?: string; ping?: string; rel?: string; target?: string; type?: string; referrerPolicy?: string; defaultChecked?: boolean; defaultValue?: string | number | string[]; ... 251 more ...; onTransitionEndCapture?: (event: TransitionEvent<...>) => void; }' is not assignable to type 'ButtonHTMLAttributes<HTMLButtonElement>'. Types of property 'type' are incompatible. Type 'string' is not assignable to type '"button" | "submit" | "reset"'.ts(2322)
Looks like there's a conflict because Typescript doesn't know the kind of ...rest
will be on the component. I can ignore the error with // @ts-ignore
and code get working, but of course this isn't the right way.
Probably it's something that I don't know how to type. Anybody can help me?