typescript 类型'( prop :属性)=>元素[]"不能赋给类型“FunctionComponent< Props>”

rn0zuynd  于 2023-01-06  发布在  TypeScript
关注(0)|答案(4)|浏览(297)

我正在尝试在React应用中添加TypeScript。
版本:

"react": "16.9.0",
"typescript": "3.5.3",

我有一个数组

import aLogo from '../images/a.svg';
import bLogo from '../images/b.svg';

const websites = [
  {
    name: 'A',
    src: aLogo,
    url: 'https://a.com',
  },
  {
    name: 'B',
    src: bLogo,
    url: 'https://b.com',
  },
];

我通过 prop 把它传递给一个组件。

interface Website {
  name: string;
  src: string;
  url: string;
}

interface Props {
  websites: Website[];
}

const SocialList: React.FC<Props> = (props: Props) => {
  const { websites } = props;

  return websites.map((website) => {
    const { name, src, url } = website;

    return (
      <a key={name} href={url}>
        <img src={src} />
      </a>
    );
  });
};

但它给了我错误

TypeScript error in /SocialList.tsx(16,7):
Type '(props: Props) => Element[]' is not assignable to type 'FunctionComponent<Props>'.
  Type 'Element[]' is missing the following properties from type 'ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<any, any, any>)>': type, props, key  TS2322

    14 | }
    15 | 
  > 16 | const SocialList: React.FC<Props> = (props: Props) => {
       |       ^

我在how do you declare an array of objects inside typescript?中阅读了答案,但仍然不知道如何修复它。

mnemlml8

mnemlml81#

您的SocialList组件呈现多个节点。虽然React版本〉= 16.0支持此行为,但React(@types/react)的类型声明不允许此行为。换句话说,您可以在JS React(v16+)中呈现多个节点,但不能在TS React中呈现。有关JS React,请参阅相关问题:Return multiple elements inside React.render().
要解决此问题,您有以下几个选项:请更新组件以使其仅返回单个节点、使用类型Assert或从TypeScript中禁用错误。

返回单个节点

您可以更新代码,在包含元素中返回a标记。默认情况下使用div,但这会使DOM混乱。您可以使用React.Fragment组件,它不会将任何内容呈现给实际的DOM,因此基本上就是您所追求的。
示例:

const SocialList: React.FC<Props> = (props: Props) => {
  const { websites } = props;

  const websiteElements = websites.map((website) => {
    const { name, src, url } = website;

    return (
      <a key={name} href={url}>
        <img src={src} />
      </a>
    );
  });

  return (
    <React.Fragment>
      {websiteElements}
    </React.Fragment>
  )
};

如果您愿意,也可以使用以下简短的片段语法:

<>
  {websiteElements}
</>

类型Assert

您可以Assert返回值的类型为any,这将导致类型错误被忽略。然而,如果您启用了它,这将与eslint规则no-explicit-any冲突(我不同意这个规则)。无论如何,我不推荐这种方法,因为您应该尽可能地避免as any(在这里是可以避免的)。
示例:

const SocialList: React.FC<Props> = (props: Props) => {
  const { websites } = props;

  return websites.map((website) => {
    const { name, src, url } = website;

    return (
      <a key={name} href={url}>
        <img src={src} />
      </a>
    );
  }) as any;
};

禁用错误

由于错误是由于@types/react的类型声明引起的,您可以通过将// @ts-ignore放在出错行的上方来抑制TS错误。您可以尝试找到一个更具体的错误来忽略,但我找不到适合这种情况的错误,所以要小心,因为这将忽略该行的 * 所有 * TS错误(例如,如果Props接受类型参数,但没有给定类型参数)。
我不推荐这种方法,因为禁用TS错误应该尽可能避免,并且从TypeScript文档:
请注意,此注解只会抑制错误报告,我们建议您谨慎使用此注解。
示例:

// @ts-ignore
const SocialList: React.FC<Props> = (props: Props) => {
  const { websites } = props;

  return websites.map((website) => {
    const { name, src, url } = website;

    return (
      <a key={name} href={url}>
        <img src={src} />
      </a>
    );
  });
};
fjnneemd

fjnneemd2#

该错误与返回JSX元素数组有关,该数组不是组件的有效返回类型。
你必须返回一个节点,你所要做的就是把它 Package 在一个片段<></>或者一个<div></div>等等里面...
此外,您无需再次键入props参数

const SocialList: React.FC<Props> = ({ websites }) => (
  <>
    {websites.map(({ name, src, url }) => (
      <a key={name} href={url}>
        <img src={src} />
      </a>
    ))}
  </>
);
zpf6vheq

zpf6vheq3#

对于您获得此错误的原因,此处接受的答案不正确。React组件 * 可以 * 返回包含React v16之后的React元素的数组。您 * 不必 * 返回片段。
这是react types包的问题,更具体地说是TS本身的问题。
源1 source 2
作为一种解决方法,您可以取消此错误消息(因为它本身是错误的),或者实际上返回一个片段

daolsyd0

daolsyd04#

JSX元素的数组为什么不是有效的返回类型?整个对话看起来很奇怪,因为从render返回数组是在2017年React@16发布时添加的。
这是相当令人失望的,发现这而不是一个真实的的解决方案。
我猜react类型在React@16之后没有更新。在我的代码中,我不得不像这样修复它:

type AdvFC<P> = (...args: Parameters<React.FC<P>>) => ReturnType<React.FC<P>> | ReturnType<React.FC<P>>[];

然后,您可以按如下方式使用它:

const SocialList: React.AdvFC<Props> = (props: Props) => ...

不知道会不会带来一些副作用,到目前为止一切顺利。

相关问题