【问题标题】:Component which prop must be an array of specific React elements组件 which prop 必须是特定 React 元素的数组
【发布时间】:2021-09-30 03:40:30
【问题描述】:

我正在尝试编写一个组件,它接受另一个组件的实例数组作为道具。该组件是MyComponent,它接受Title 的实例数组作为其参数之一。但是,我无法让 TypeScript 输入检查:

import * as React from "react";


type TitleProps = {
    name: string;
};

function Title(props: TitleProps) {
    return null;
}

type MyComponentProps = {
    titles: Array<React.ReactElement<TitleProps>>;
}

function MyComponent({ titles }: MyComponentProps) {
    return <div>{titles}</div>;
}

function OtherComponent(props: {}) { return null }

const shouldError = <MyComponent titles={[ <div/>, <OtherComponent/> ]} />;
const shouldNotError = <MyComponent titles={[ <Title name="hi"/>, <Title name="hi2"/>, ]} />;

如您所见,我可以将任何我想要的东西传递给 titles 属性,而不仅仅是 &lt;Title/&gt; 的实例。

TypeScript Playground URL

【问题讨论】:

  • 我希望操场在最后一行出错,因为我将&lt;div/&gt; 传递给titles,它应该是Title 实例的数组,例如[&lt;Title/&gt;, ...]..
  • @DavidGomes 我了解错误是什么,但该游乐场并没有为问题添加任何新内容。当您添加指向 Playground 的链接时,人们会期望他们可以在那里尝试。
  • 我认为这个问题更多地与typescript处理JSX的方式有关,没有错误,因为任何元素都是JSX.Element,当我们使用react处理JSX时,它也是一个ReactElement。没有办法通过 JSX 标签来限制元素,因为本质上,它们是函数的结果,道具或标签不再重要。这个答案有更详细的解释:stackoverflow.com/a/59418019/10922948
  • PS 为什么将子组件作为道具传递而不是嵌套组件/使用 React 子组件?

标签: reactjs typescript


【解决方案1】:

Typescript 中JSX.Element 的类型安全功能尚不可用。

我们之前也遇到过类似的情况,我们所做的不是使用 JSX.Element 的数组,而是使用相同元素可以拥有的 props 数组。然后在渲染过程中,我们简单地将 props 数组映射到 JSX.Element 数组。

import * as React from "react";

type TitleProps = {
  name: string;
};

function Title(props: TitleProps) {
  return null;
}

type MyComponentProps = {
  titles: TitleProps[];
};

function MyComponent({ titles }: MyComponentProps) {
  return (
    <React.Fragment>
      {titles.map(titleProps => (
        <Title {...titleProps} />
      ))}
    </React.Fragment>
  );
}

// no errror
const shouldNotError = (
  <MyComponent titles={[{ name: "React" }, { name: "fixme" }]} />
);

//error
const shouldError = (
  <MyComponent titles={[{ other: "don't use this" }, { another: "help" }]} />
);

【讨论】:

    【解决方案2】:

    TypeScript 不是灵丹妙药。在许多情况下,保证 100% 的类型安全需要在代码中引入额外的复杂性,或者根本不可能。你遇到过这样一种情况。

    an open GitHub issue on the subject of typing JSX elements。最好的选择是等待 TypeScript 引入特定的机制。

    否则 (from Matt McCutchen's answer):

    所有 JSX 元素都被硬编码为具有 JSX.Element 类型,因此无法接受某些 JSX 元素而不接受其他元素。如果你想要这种检查,你将不得不放弃 JSX 语法,定义你自己的元素工厂函数来包装 React.createElement 但为不同的组件类型返回不同的元素类型,并手动编写对该工厂函数的调用。

    所以目前还没有办法确保任何 JSX 元素的类型安全

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-09
      • 1970-01-01
      • 1970-01-01
      • 2021-08-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多