Search code examples
cssreactjstypescriptstyled-componentsemotion

Problem with typescript using emotion/styled component


Current behavior:

I have a problem using typescript and emotion/styled when I want to set the type of the parent component that wrappes a styled component.

I have this parent component that wrappes a styled component

// button/index.tsx

import { ButtonStyled } from "./Button.styles";
import { ButtonProps } from "./Button.interface";

const Button = ({
  variant = "primary",
  ...rest
}: ButtonProps): typeof ButtonStyled => <ButtonStyled {...rest} />;

export default Button;
// button/Button.styles

import styled from "@emotion/styled";

export const ButtonStyled = styled.button`
  padding: 0.4em;
  width: 100%;
  border: 0;
`;

When I set the return type of Button ( typeof ButtonStyled ) it gets me this error:

_Type 'ReactElement<any, any>' is missing the following properties from type 'StyledComponent<{ theme?: Theme; as?: ElementType; }, DetailedHTMLProps<ButtonHTMLAttributes, HTMLButtonElement>, {}>': withComponent, _emotion_styles

image

This is important because in another file I want to extend the styles of the button

import styled from "@emotion/styled";

import Button from "components/button";

export const SubmitButton = Button.withComponent`
background: #333;
color: #fff;
`;

But it can't be do it because it throws this error:

Property 'withComponent' does not exist on type '({ variant, ...rest }: ButtonProps) => StyledComponent<{ theme?: Theme; as?: ElementType; }, DetailedHTMLProps<ButtonHTMLAttributes, HTMLButtonElement>, {}>'.

Environment information:

  • next version: 10.2.3
  • react version: 17.0.2
  • @emotion/react version: 11.4.0
  • @emotion/styled version: 11.3.0

Solution

  • There are some issues with your code:

    • the return type of the Button function in button/index.tsx is not a React.Component or typeof ButtonStyled. It's JSX.Element
    • accounting for that the type of the Button itself is (props: ButtonProps) => JSX.Element. It's a function. It definitely doesn't have withComponent property.

    I guess what you really want to achieve is something like that:

    // -------- button/Button.styles
    export const ButtonStyled = styled.button`
      padding: 0.4em;
      width: 100%;
      border: 0;
    `;
    // -------- button/index.tsx
    const Button = ({ variant = "primary", ...rest }: ButtonProps) => (
      <ButtonStyled {...rest} />
    );
    // --------
    export const SubmitButton = styled(ButtonStyled)`
      background: #333;
      color: #fff;
    `.withComponent(Button);