在React函数式组件中使用TypeScript属性辨识。

3
我正在创建一个动态小部件,可以为空或已填充。默认情况下应为空。当 populated={true} 时,我希望 totalGrosstotalNet 值是必需的。否则,这两个属性不应被允许。
为此,我尝试使用辨别联合类型 (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 错误? TS Error

totalNettotalGross 分配默认值应该可以解决即时错误(即 totalNet ='',totalGross ='')。然而,我认为 WidgetBodyProps 的方式有点笨拙,特别是 never 的用法。我猜后者是因为你想避免使用类型保护? - miqh
2个回答

2
一旦您解构了props,Typescript就会忘记它们有任何关联。因此,对一个变量进行测试不会区分另一个变量的类型。但是,在解构props时,您尚未测试其类型,因此所有变量都具有所有可能性的类型。
然而,如果避免解构,则Typescript可以跟踪props的类型。这样,测试props的属性将缩小您所期望的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

工作示例


0
通常出现这个错误是因为Typescript不相信你的某些东西不是null。使用非空断言运算符告诉Typescript它可以相信你知道自己在做什么,你不会传递一个null给它。另一种选择是确保相关变量被正确设置为空字符串。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接