0

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.

1 Answer 1

1

You're passing label as children prop, you need to pass it explicitly instead:

<StyledButton
  primary={primary}
  size={size}
  onClick={onClick}
  label={label}
/>;     
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.