I'm fairly new to Typescript and I'm getting a strange error when using TS in conjunction with styled-components - specifically when I try to use the styled component:
Here is my props type declaration:
export interface ButtonProps {
primary: boolean;
size: "small" | "medium" | "large";
label: string;
onClick: (
event: React.MouseEvent<HTMLButtonElement, MouseEvent>
) => void;
};
Here is where I create my styled component:
const StyledButton = styled.button<ButtonProps>`
${ButtonStyles.buttonBase};
${({ primary }) => primary ? ButtonStyles.primary : ButtonStyles.secondary}
${({ size }) => ButtonStyles[size]}
`
Here's the main component implementation, where I try to use my styled component:
const Button = ({
primary,
size,
onClick,
label
}: ButtonProps) => {
return (
<StyledButton //<== error occurs here
primary={primary}
size={size}
onClick={onClick}
>
{label}
</StyledButton>
);
}
And my declaration of default props:
Button.defaultProps = {
primary: false,
size: "medium"
}
The error VS Code is giving me is below (it's rather long and verbose):
No overload matches this call.
Overload 1 of 2, '(props: { form?: string | undefined; label: string; slot?: string | undefined; style?: CSSProperties | undefined; title?: string | undefined; ref?: ((instance: HTMLButtonElement | null) => void) | RefObject<...> | null | undefined; ... 264 more ...; size: "small" | ... 1 more ... | "large"; } & { ...; } & { ...; }): ReactElement<...>', gave the following error.
Property 'label' is missing in type '{ children: string; primary: boolean; size: "small" | "medium" | "large"; onClick: (e: MouseEvent<HTMLButtonElement, MouseEvent>) => void; }' but required in type '{ form?: string | undefined; label: string; slot?: string | undefined; style?: CSSProperties | undefined; title?: string | undefined; ref?: ((instance: HTMLButtonElement | null) => void) | RefObject<...> | null | undefined; ... 264 more ...; size: "small" | ... 1 more ... | "large"; }'.
Overload 2 of 2, '(props: StyledComponentPropsWithAs<"button", any, ButtonProps, never, "button", "button">): ReactElement<StyledComponentPropsWithAs<"button", any, ButtonProps, never, "button", "button">, string | JSXElementConstructor<...>>', gave the following error.
Property 'label' is missing in type '{ children: string; primary: boolean; size: "small" | "medium" | "large"; onClick: (e: MouseEvent<HTMLButtonElement, MouseEvent>) => void; }' but required in type '{ form?: string | undefined; label: string; slot?: string | undefined; style?: CSSProperties | undefined; title?: string | undefined; ref?: ((instance: HTMLButtonElement | null) => void) | RefObject<...> | null | undefined; ... 264 more ...; size: "small" | ... 1 more ... | "large"; }'.ts(2769)
Button.tsx(17, 3): 'label' is declared here.
Button.tsx(17, 3): 'label' is declared here.
It seems like the problem is with Typescript understanding the label prop, but being somewhat inexperienced with TS I'm struggling to understand the problem and find a solution.
When I change the ButtonProps interface to make label optional, the error goes away, so it looks like I was passing label with no guarantee it would have a non-null value.
However, if I revert it to a required value and then pass a default value for label in Button.defaultProps (guaranteeing it will always have a non-null value), the error does not go away.
I would appreciate any explanation of what's going on here, the proper way(s) to solve this error, and any refactor of this component that might avoid this issue in the future.