typescript 是否有可能在父组件中Assert一个属性的类型,然后才到达使用相同属性的子组件

hgqdbh6s  于 12个月前  发布在  TypeScript
关注(0)|答案(1)|浏览(123)

bounty将在6天后过期。回答此问题可获得+300声望奖励。23k希望引起更多关注此问题。

我有一个组件NotFoundGuard,它只在给定条件为真时才呈现子组件。否则,它会呈现一个通用的回退组件,以尝试避免在我们的代码库中非常常见的一些冗余。
我试图找出是否有可能在到达子组件时向TypeScriptAssertproduct不是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 />;
}


我想避免使用!操作符进行Assert。更新组件以获取渲染属性可能会很好,但我对“类型魔术”更感兴趣,即使它有点古怪。
我的尝试看起来像这样,毫不奇怪,没有工作。

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 />;
}


有没有可能让typehints在这样的场景中正确工作?

<NotFound if={product != null}>
  <ProductDisplay product={product} /> // No type error here about potential null prop
</NotFound>

bq9c1y66

bq9c1y661#

就个人而言,我会给予完全放弃<NotFound />,并将其简化为:

{
  product === null ? <Fallback /> : <ProductDisplay product={product} />
}

字符串
但是让我们把它放在一边-保留<NotFound />(让我们假设它有更多的业务逻辑,我们不想暴露/重复到当前包含<NotFound />的所有组件中)-正确的解决方案,恕我直言,是Assert操作符:

<NotFound if={product !== null}>
  <ProductDisplay product={product!} />
</NotFound>


问题的关键是TS不知道if在类型方面做什么。
因此,我们必须想出一种方法,以TS理解的方式将我们的自定义逻辑通知给父组件。

<NotFound if={product !== null}>
  {
    product !== null && <ProductDisplay product={product} />
  }
</NotFound>


在我看来,这更糟
让我们退后一步,问问自己:“Assert运算符是用来做什么的?它为什么存在?"
这是针对TS不能正确判断表达式的可空性的情况。在这种情况下,我们绝对肯定product不会作为null传递给<ProductDisplay />,但TS不能确定这一点。
所以Assert操作符在这里不是一个错误,而是一个精确的正确解决方案。它是专门为这种情况开发的,我们应该使用它。* 1 *
用你自己的话来说,这就是你一直在寻找的“类型魔法”。

  • 1*-Assert操作符的错误用法是禁止有效的警告(在本例中,如果将product作为null传递给<ProductDisplay />的可能性确实存在)。

相关问题