reactjs - Emotion Js och TypeScript-problem när man skickar props till styled


jag fick dessa fel:

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

på den här koden:

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

Jag tänkte att problemet var relaterat till min kod, men efter att ha gjort alla tester tror jag att det inte är det

Jag letade efter detta fel eller lösningar och jag hittade inget

min 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"]
}

min Tsx-kod:

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;

Min stil med känsla

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')};
`;

och här har jag en gif där jag renderar min komponent, men precis efter dyker felet upp

Svar #1

När du arbetar med JSS-bibliotek (såsom Emotion och Styled Components) och TypeScript, för att få props att fungera måste du ange generics som specificerar typerna. Detta kan göras med hjälp av gränssnitt eller typalias.

För ditt fall behöver du specificera att Hamburger har HamburguerProps genom att använda styled<HamburguerProps>:

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

Svar #2

Om du försöker utöka stilarna för en befintlig komponent (med styled-components eller @emotion/styled), kommer syntaxen att vara något annorlunda. Till exempel, om vi har en BaseButton som vi försöker utöka:

interface BaseButtonProps {
  color: string
}

const BaseButton = styled.button<BaseButtonProps>`
  ${props => {
    if (props.color === 'red') {
      return `
        color: red;
      `;
    }

    return `
      color: green;
    `;
  }}
`;

...

interface HamburguerProps extends BaseButtonProps {
  open: boolean
}

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

Se till att du placerar HamburguerProps-gränssnittsargumentet på HÖGER sida

styled(BaseButton)<HamburguerProps>

och INTE vänstra sidan

styled<HamburguerProps>(BaseButton)

Relaterade artiklar