将道具传递给样式时的 Emotion Js 和 TypeScript 问题

Emotion Js and TypeScript problems when passing props to styled

我遇到了这个错误:

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

关于此代码:

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

我以为问题出在我的代码上,但是做了所有测试,我相信不是这样

我查找了此错误或解决方案,但没有找到

我的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"]
}

我的 Tsx 代码:

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;

我的情感风格

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

这里我有一个 gif,我在其中渲染了我的组件,但就在错误出现之后

当您使用 JSS 库(例如 Emotion 和 Styled Components)和 TypeScript 时,要使 props 正常工作,您必须提供指定类型的泛型。这可以通过使用接口或类型别名来完成。

对于您的情况,您需要使用 styled<HamburguerProps>:

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

如果您尝试 extend the styles 现有组件(使用 styled-components@emotion/styled),语法将略有不同。例如,如果我们有一个要扩展的 BaseButton

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

确保将 HamburguerProps 接口参数放在右侧

styled(BaseButton)<HamburguerProps>

而不是左侧

styled<HamburguerProps>(BaseButton)