7

这是场景:

我有一个自定义组件:

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> { ... }

<SubComponent2 />我希望 SubComponent1 是 SuperComponent 的唯一有效子代,也就是说,如果我将或 Other types 作为子级,我希望 typescript 可以抛出错误<SuperComponent>

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

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

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

4

2 回答 2

12

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

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

于 2018-10-10T03:39:42.770 回答
0

我可能会声明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 } />) }

    ...
  );
};
于 2019-12-19T22:59:30.100 回答