【问题标题】:Typescript prop discrimination in react functional component反应功能组件中的打字稿道具歧视
【发布时间】:2021-04-20 01:02:49
【问题描述】:

我正在创建一个动态小部件,它可以是空的,也可以是填充的。默认情况下它应该是空的。当populated={true} 时,我希望需要totalGrosstotalNet 值。否则,这 2 个道具不应该被允许。

为此,我尝试使用区分类型 (WidgetBodyProps)。但是,TypeScript 会抱怨,因为 totalNettotalGross<WidgetBodyPopulated /> 中必需的道具

type WidgetBodyProps =
    | { isEmpty?: false; totalNet: string; totalGross: string }
    | { isEmpty: true; totalNet?: never; totalGross?: never };

type WidgetProps = WidgetHeaderProps & WidgetBodyProps;

const Widget = (props: WidgetProps) => {
    const { title = "", isEmpty = true, totalNet, totalGross } = props;

    return (
        <Card>
            <Box>
                <WidgetHeader title={title} />
                <Divider my="4" />
                {isEmpty ? (
                    <WidgetBodyEmpty flex="1" />
                ) : (
                    <WidgetBodyPopulated totalNet={totalNet} totalGross={totalGross} />
                )}
            </Box>
        </Card>
    );
};

如何解决这个 Typescript 错误?

【问题讨论】:

  • totalNettotalGross 分配默认值应该可以修复直接错误(即totalNet = '', totalGross = '')。但是,我认为WidgetBodyProps 的方式似乎有点笨拙,尤其是never 的用法。我猜后者是因为你想使用类型保护来躲避?

标签: javascript reactjs typescript typeerror


【解决方案1】:

通常会发生此错误,因为 Typescript 不相信某些内容不为空。使用non-null assertion operator 告诉 Typescript,它可以相信你知道自己在做什么,并且不会给它一个空值。另一种选择是确保将相关变量正确设置为空字符串。

【讨论】:

    【解决方案2】:

    一旦你解构了道具,Typescript 就会忘记它们曾经是相关的。因此,对一个变量的测试不会区分另一个变量的类型。但是在你解构 props 的时候,你还没有测试它的类型,所以所有的变量都被输入了所有的可能性。

    但是,如果您避免解构,那么 Typescript 可以密切关注 props 的类型。通过这种方式测试道具属性可以缩小您所期望的道具类型。

    {props.isEmpty ? (
        <WidgetBodyEmpty flex="1" />
    ) : (
        <WidgetBodyPopulated
          totalNet={props.totalNet}
          totalGross={props.totalGross}
        />
    )}
    

    然后你甚至可以将这些道具简化为:

    type WidgetBodyProps =
        | { isEmpty?: false; totalNet: string; totalGross: string }
        | { isEmpty: true };
    

    因为你永远不会访问.totalNet而不先检查.isEmpty

    Working example

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-11-18
      • 2020-04-08
      • 2021-03-19
      • 2021-02-12
      • 2021-07-01
      • 2020-07-26
      • 1970-01-01
      相关资源
      最近更新 更多