Search code examples
reactjstypescriptemotion

Emotion Js and TypeScript problems when passing props to styled


i got this errors:

No overload matches this call.   Overload 1 of 2, '(...styles: Interpolation<Pick<DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "form" | ... 264 more ... | "value"> & { ...; }>[]): StyledComponent<...>', gave the following error.
    Argument of type 'TemplateStringsArray' is not assignable to parameter of type 'Interpolation<Pick<DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "form" | ... 264 more ... | "value"> & { ...; }>'.
      Type 'TemplateStringsArray' is not assignable to type 'ObjectInterpolation<Pick<DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "form" | ... 264 more ... | "value"> & { ...; }>'.
        Types of property 'filter' are incompatible.
          Type '{ <S extends string>(callbackfn: (value: string, index: number, array: readonly string[]) => value is S, thisArg?: any): S[]; (callbackfn: (value: string, index: number, array: readonly string[]) => unknown, thisArg?: any): string[]; }' is not assignable to type 'string | string[] | undefined'.
            Type '{ <S extends string>(callbackfn: (value: string, index: number, array: readonly string[]) => value is S, thisArg?: any): S[]; (callbackfn: (value: string, index: number, array: readonly string[]) => unknown, thisArg?: any): string[]; }' is missing the following properties from type 'string[]': pop, push, concat, join, and 27 more.   Overload 2 of 2, '(template: TemplateStringsArray, ...styles: Interpolation<Pick<DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "form" | ... 264 more ... | "value"> & { ...; }>[]): StyledComponent<...>', gave the following error.
    Argument of type '(props: HamburguerProps) => "250px" | "0"' is not assignable to parameter of type 'Interpolation<Pick<DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "form" | ... 264 more ... | "value"> & { ...; }>'.
      Type '(props: HamburguerProps) => "250px" | "0"' is not assignable to type 'FunctionInterpolation<Pick<DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "form" | ... 264 more ... | "value"> & { ...; }>'.
        Types of parameters 'props' and 'mergedProps' are incompatible.
          Property 'open' is missing in type 'Pick<DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "form" | ... 264 more ... | "value"> & { ...; }' but required in type 'HamburguerProps'.  TS2769

on this code:

> 25 | export const Hamburguer = styled('button')`
       |                           ^
    26 |   position: absolute;
    27 |   left: ${(props: HamburguerProps) => (props.open ? '250px' : '0')};
    28 | `;

I was thinking that the problem was related to my code, but doing all the tests, I believe it is not that

I looked for this error or solutions and I didn't find

my TsConfig

{
  "compilerOptions": {
    "target": "es5",
    "types": ["node", "@emotion/core"],
    "lib": ["dom", "dom.iterable", "esnext"],
    "baseUrl": "src",
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react"
  },
  "include": ["src"]
}

my Tsx code:

import Logo from 'assets/images/Logo.png';
import { useSelector, useDispatch } from 'react-redux';
import { toggleSide } from 'redux/slices/sideBar';

interface RootState {
  sideBarStatus: boolean;
}

interface SideBar {
  isOpen: boolean;
}

const LogoNavigation: React.FC<SideBar> = ({ isOpen }) => {
  const dispatch = useDispatch();
  return (
    <LogoSide>
      <img src={Logo} alt="Logo Elo Ghost" />
      <Hamburguer open={isOpen} onClick={() => dispatch(toggleSide(!isOpen))}>
        <div />
        <div />
        <div />
      </Hamburguer>
    </LogoSide>
  );
};

const SideNavigation: React.FC = () => {
  // const { sideIsOpen } = useSelector((RootState) => RootState.toggleSide);
  const selectIsOpen = (state: RootState) => state.sideBarStatus;
  const sideBarStatus = useSelector(selectIsOpen);
  return (
    <SideNav>
      <LogoNavigation isOpen={sideBarStatus} />
    </SideNav>
  );
};

export default SideNavigation;

My Styles with emotion

import styled from '@emotion/styled';

type HamburguerProps = {
  open: boolean;
};

export const SideNav = styled('nav')`
  max-width: 250px;
  width: 100%;
  height: 100vh;
  background: #437fb9;
`;

export const LogoSide = styled('div')`
  display: flex;
  justify-content: space-between;
  width: 100%;
  height: 60px;
  background: #fdca40;
  img {
    height: 50px;
  }
`;

export const Hamburguer = styled('button')`
  position: absolute;
  left: ${(props: HamburguerProps) => (props.open ? '250px' : '0')};
`;

and here I have a gif where I render my component, but right after the error appears

enter image description here


Solution

  • When you are working with JSS libraries (such as Emotion and Styled Components) and TypeScript, to make the props work, you will have to provide the generics which specifies the typings. This can be done with the use of interfaces or type aliases.

    For your case, you will need to specific that Hamburger has the HamburguerProps by using styled<HamburguerProps>:

    export const Hamburguer = styled.button<HamburguerProps>`
      position: absolute;
      left: ${(props) => (props.open ? '250px' : '0')};
    `;