【问题标题】:Passing union typed props to react child component requiring one of the types in the union传递联合类型的道具以反应需要联合中的一种类型的子组件
【发布时间】:2018-05-21 12:02:31
【问题描述】:

在 Typescript+React 中。我有两个组件(模块),它们具有通过接口指定的特定类型。此外,我还有一个父组件,它接受一个数组,其中一个联合指定为道具。

子组件:

模块一

interface IModuleOneProps {
  moduleOneSpecificProp: string;
  module_type: sting;
  commonProp: string;
}

const ModuleOne: React.SFC<IModuleOneProps> = props => {
  return (
    <p>{moduleOneSpecificProp + " " + commonProp}</p>
  );
};

export default ModuleOne;

模块二

interface IModuleTwoProps {
  moduleTwoSpecificProp: string;
  module_type: sting;
  commonProp: string;
}

const ModuleTwo: React.SFC<IModuleTwoProps> = props => {
  return (
    <p>{moduleTwoSpecificProp + " " + commonProp}</p>
  );
};

export default ModuleTwo;

包含模块数组的容器组件,可以是两种类型:

interface IContainerModuleProps {
modules: Array<
    IModuleOneProps | IModuleTwoProps
  >;
}

class ContainerModule extends React.Component<IContainerModuleProps> {

  public render() {
    const module = this.props.modules[1];
    switch (module.module_type) {
      case 'module_one':
        return <ModuleOne {...module} />;
      case 'module_two':
        return <ModuelTwo {...module} />;
    }
  }
}

但是 TypeScript 不会让我在渲染组件时传播 module。它抱怨类型。

Type '{ commonProp: string; moduleOneSpecificProp: string; }' is not assignable to type 'IntrinsicAttributes & IModuleOneProps & { children?: ReactNode; }'.
  Type '{ commonProp: string; moduleTwoSpecificProp: string; }' is not assignable to type 'IntrinsicAttributes & IModuleOneProps & { children?: ReactNode; }'.
    Property 'moduleOneSpecificProp' is missing in type '{ commonProp: string; moduleTwoSpecificProp: string; }'.

有没有我在这里看不到的快速修复?还是必须先重建 prop 对象 (module),然后再将其传递给子组件?

【问题讨论】:

  • module_type 属性如何定义?
  • @AlekseyL。抱歉,刚刚将其添加到接口中。这是在基于 api 调用的早期函数中填充的。
  • 我刚刚设法解决了这个问题。基于stackoverflow.com/questions/42156270/…。我会尽快写出我的解决方案。编辑:提香打败了我!

标签: javascript reactjs typescript ecmascript-6


【解决方案1】:

如果这样做,您需要将module_type 属性定义为字符串文字类型(一种只有一个值的字符串类型),然后switch 将正确键入保护:

interface IModuleOneProps {
    moduleOneSpecificProp: string;
    commonProp: string;
    module_type: "module_one"
}
interface IModuleTwoProps {
    moduleTwoSpecificProp: string;
    commonProp: string;
    module_type: "module_two"
}
interface IContainerModuleProps {
    modules: Array<
    IModuleOneProps | IModuleTwoProps
    >;
}

public render() {
    const module = this.props.modules[1];
    switch (module.module_type) {
        case 'module_one':
            return <ModuleOne {...module} />;
        case 'module_two':
            return <ModuleTwo {...module} />;
    }
}

也完全可以对字符串文字使用枚举以避免依赖于魔术字符串:

enum MODULE_NAME {
  MODULE_ONE,
  MODULE_TWO
}

然后在界面和渲染方法中都使用MODULE_NAME.MODULE_ONE

【讨论】:

  • 谢谢,刚刚找到那个解决方案。这实际上是添加一个新属性(我根据typescriptlang.org/docs/handbook/advanced-types.html 将其命名为kind),因为module_type 属性正在由API 调用填充。
  • @PerEnström 当我看到你的评论时,我刚刚发布了我的答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-31
  • 1970-01-01
  • 2021-06-04
  • 2021-04-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多