提问人:23k 提问时间:11/16/2023 更新时间:11/24/2023 访问量:116
是否可以在父组件到达使用相同 prop 的子组件之前在父组件中断言 prop 的类型
Is it possible to assert a prop's type in parent component before it reaches children that use the same prop
问:
我有一个组件,它仅在给定条件为真时才呈现子项。否则,它会呈现一个通用的回退组件,以尝试避免在我们的代码库中很常见的东西上出现一些冗余。NotFoundGuard
我正在尝试找出是否可以断言到 TypeScript,而不是在它到达子组件时product
null
<NotFound if={product != null}>
<ProductDisplay product={product} /> <- Type 'Product | null' not assignable to type 'Product'
</NotFound>
该组件大致如下所示NotFound
type Props = { if: boolean };
function NotFound(prop: Props): ReactNode {
if (!props.if) {
return children;
}
return <Fallback />;
}
我想避免与操作员断言。更新组件以采用渲染道具可能会正常工作,但我对“类型魔术”更感兴趣,即使它有点笨拙。!
我的尝试看起来像这样,不出所料没有奏效。
type Props = { if: boolean };
function dummyAssert(cond: boolean): asserts cond is true {}
function NotFound(prop: Props): ReactNode {
if (!props.if) {
dummyAssert(props.if);
return children;
}
return <Fallback />;
}
在这种情况下,是否有可能让类型提示正常工作?
<NotFound if={product != null}>
<ProductDisplay product={product} /> // No type error here about potential null prop
</NotFound>
答:
就我个人而言,我会完全放弃并简化为:<NotFound />
{
product === null ? <Fallback /> : <ProductDisplay product={product} />
}
但是,让我们把它放在一边——并保留(假装它有更多的业务逻辑,或者我们不想将这个逻辑暴露/重复到包含)的组件中——恕我直言,正确的解决方案是非空断言运算符:<NotFound />
<NotFound />
<NotFound if={product !== null}>
<ProductDisplay product={product!} />
</NotFound>
为什么?
问题的关键在于,TS 不知道在类型方面有什么作用。
因此,我们必须在父组件中以 TS 理解的方式告知它我们的自定义逻辑(包含在指令中)。这意味着使用非 null 运算符的替代方法是if
if
<NotFound if={product !== null}>
{
product !== null && <ProductDisplay product={product} />
}
</NotFound>
在我看来,这更糟(我们必须重复 JSX 标记内部的内容)。if
现在让我们退后一步,问问自己:“什么是非空断言运算符?它为什么存在,什么时候应该使用?
它适用于 TS 无法正确确定表达式的可为 null 性的情况。在这种情况下,我们绝对肯定地知道不能传递 ,但 TS 无法确定这一点。1product
null
<ProductDisplay />
因此,非空断言运算符在这里不是错误/黑客/扫荡,而是正确的解决方案。它正是为像我们这样的情况开发的,我们应该使用它。阿拉伯数字
用你自己的话来说,这就是你一直在寻找的“类型魔力”。
1 - 如果你好奇为什么 TS 无法了解指令的作用,那是因为 TS 无法深入了解 React 如何解释 JSX 以创建 DOM 元素,以及这些 DOM 元素之间的关系是什么,一旦创建。简而言之,TS 不知道在 React 组件的上下文中代表什么。
2 - 非 null 运算符的错误用法是禁止有效警告(在本例中,如果传递的可能性实际存在)。if
children
product
null
<ProductDisplay />
评论
product
null
product
null