类型 'string' 不可分配给类型 'undefined'。 TS2769

时间:2021-07-02 13:40:50

标签: javascript reactjs typescript styled-components

我根据 href 类型添加了一些条件样式。出于某种原因,如果我将 as 添加到 Button styled-component 中,我会收到 TS 错误:Type 'string' is not assignable to type 'undefined'. TS2769

组件

interface LinkProps {
  to: string;
  target?: string;
  as?: string;
  className?: string;
  children: ReactChildren | React.ReactNode | string;
}

const Button = styled(RLink)`
  text-decoration: none;
`;

export const Link = ({
  to,
  target,
  children,
  as = 'a',
  className
}: LinkProps) => {
  return (
    <Button
      as={as}
      to={to}
      target={target}
      rel="noopener"
      className={className}
    >
      {children}
    </Button>
  );
};

没有 as

enter image description here

没有 as

enter image description here

完整的 TS 错误

index.js:1 /frontend/claim-handler/src/components/shared/Link/index.tsx
TypeScript error in /frontend/claim-handler/src/components/shared/Link/index.tsx(39,6):
This JSX tag's 'children' prop expects type 'never' which requires multiple children, but only a single child was provided.  TS2745

37 | }: LinkProps) => {
  38 |   return (
    > 39 |     <Button
           |      ^
40 |       as={as}
        41 |       to={to}
        42 |       target={target}
console.<computed> @ index.js:1
handleErrors @ webpackHotDevClient.js:174
push.../../node_modules/react-dev-utils/webpackHotDevClient.js.connection.onmessage @ webpackHotDevClient.js:213


index.js:1 /frontend/claim-handler/src/components/shared/Link/index.tsx
TypeScript error in /frontend/claim-handler/src/components/shared/Link/index.tsx(40,7):
No overload matches this call.
Overload 1 of 2, '(props: Omit<Omit<import("/node_modules/@types/react-router-dom/index").LinkProps<unknown> & RefAttributes<HTMLAnchorElement> & LinkProps, never> & Partial<...>, "theme"> & { ...; } & { ...; }): ReactElement<...>', gave the following error.
  Type 'string' is not assignable to type 'undefined'.  TS2769

  38 |   return (
    39 |     <Button
    > 40 |       as={as}
      |       ^
      41 |       to={to}
      42 |       target={target}
      43 |       rel="noopener"

编辑

通过删除我不同意的选项 as,因为这些类型不是组件期望接收的道具,而不仅仅是参数?

以下是新错误:

enter image description here

1 个答案:

答案 0 :(得分:1)

主要问题是您试图将非常宽的类型 string 传递给 prop 接受相当大但仍然精确定义的一组字符串作为原生 html tags 的名称。 如果您只想将 as 标签的名称(即不是其他功能或类组件)作为 html 属性传递,您可以像这样输入 as

interface LinkProps {
  to: string;
  target?: string;
  as?: keyof JSX.IntrinsicElements;
  className?: string;
  children: ReactChildren | React.ReactNode | string;
}

那应该可以解决您的问题。

还有一个小问题。 虽然自己输入 children prop 是完全可以的。这是相当脆弱的方式。而你已经猜错了。 ReactChildren 不是反应孩子数组的类型。这是一种 React.Children 接口,结合了实用函数以与 children 道具一起使用。

对于输入 children prop react 公开特殊帮助类型 React.PropsWithChildren。如果您希望以更稳定的方式重写代码:

import * as React from 'react'
import styled from 'styled-components'

interface LinkProps {
    to: string;
    target?: string;
    as?: keyof JSX.IntrinsicElements;
    className?: string;
}

const Button = styled(RLink)`
    text-decoration: none;
`;

export const Link = ({
    to,
    target,
    children,
    as = 'a',
    className
}: React.PropsWithChildren<LinkProps>) => {
    return (
        <Button
            as={as}
            to={to}
            target={target}
            rel="noopener"
            className={className}
        >
            {children}
        </Button>
    );
};