【问题标题】:React Component children typecheck with typescript使用打字稿进行反应组件子类型检查
【发布时间】:2019-03-14 21:08:35
【问题描述】:

这是场景:

我有一个自定义组件:

class MyComponent extends React.Component {
  render () {
    return (
      <SuperComponent>
        <SubComponent1 />  // <- valid child
      </SuperComponent>
    )
}

class MyComponent extends React.Component {
  render () {
    return (
      <SuperComponent>
        <SubComponent2 />  // <- No! It's not right shape
      </SuperComponent>
    )
}

并且引用的 SuperComponent 和 SubComponent1 是:

interface superPropsType = {
  children: ReactElement<subPropsType1>
}
class SuperComponent extends React.Component<superPropsType> { ... }


interface subPropsType1 = {
  name: string
}
class SubComponent1 extends React.Component<subPropsType1> { ... }


interface subPropsType2 = {
  title: string
}
class SubComponent2 extends React.Component<subPropsType2> { ... }

我希望 SubComponent1 是 SuperComponent 的唯一有效子代,也就是说,如果我将 &lt;SubComponent2 /&gt; 或其他类型作为 &lt;SuperComponent&gt; 的子代,我希望 typescript 可以抛出错误

似乎 typescript 只检查子级是否应该具有 ReactElement 的类型,但 ts 不会检查该子级的道具形状(即 subPropsType1),也就是说,如果我将字符串或数字放置为SuperComponent 的子组件,ts 会抱怨类型要求不满足,但是如果我在这里放置任何 jsx 标签(将转译为 ReactElement),ts 将保持沉默

有什么想法吗?如果需要在此处发布任何配置,请随时询问

非常感谢任何想法和解决方案

【问题讨论】:

    标签: reactjs typescript tsx


    【解决方案1】:

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

    an open suggestion,它可能会在 TypeScript 3.2(将于 2018 年 11 月下旬发布)尽快实现,以便 TypeScript 根据给定组件的工厂函数的实际返回类型为 JSX 元素分配类型类型。如果实现了,您将能够定义自己的工厂函数来包装React.createElement 并使用jsxFactory 编译器选项指定它,您将获得额外的类型信息。或者@types/react 甚至会改变,以便React.createElement 提供更丰富的类型信息,如果这样做不会对不关心功能的项目造成有害后果的话;我们将不得不拭目以待。

    【讨论】:

      【解决方案2】:

      我可能会将SuperPropsType.children 声明为:

      children: React.ReactElement<SubPropsType1> | React.ReactElement<SubPropsType1>[];
      

      考虑同时拥有一个和多个孩子的可能性。

      无论如何,正如已经指出的那样,这不会按预期工作。

      你可以做的是声明一个道具,比如说subComponentProps: SubPropsType1[],传递你需要的道具来创建那些SubComponent1s,而不是它们的JSX,并在SuperComponent中渲染它们:

      interface SuperPropsType {
        children?: never;
        subComponentProps?: SubPropsType1[];
      }
      
      ...
      
      const SuperComponent: React.FC<SuperPropsType> = ({ subComponentProps }) => {
        return (
          ...
      
          { subComponentProps.map(props => <SubComponent1 key={ ... } { ...props } />) }
      
          ...
        );
      };
      

      【讨论】:

        猜你喜欢
        • 2021-04-09
        • 2021-05-12
        • 2017-06-24
        • 1970-01-01
        • 2023-04-02
        • 2020-12-25
        • 2018-11-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多