【问题标题】:Typescript and type inference: issue with validation打字稿和类型推断:验证问题
【发布时间】:2021-01-14 15:00:17
【问题描述】:

我目前有一个与此类似的函数(为了讨论,我写了一个最小工作示例):

interface Variable {
  someMethod: () => void
}

const validateVariable(variable: Variable | undefined) {
  if(!variable) {
    throw new Error('Variable is undefined!')
  }
}

const doSomething = async (): void => { 
  // maybeGetSomething returns a Variable or undefined
  // depends on the database, so both cases are definitely possible
  const variable: (Variable | undefined) = await maybeGetSomething()

  validateVariable(variable)

  variable.someMethod()
}

但 Typescript 抱怨 variable 可能未定义。我不喜欢将validateVariable 的代码放在doSomething 中的想法,因为在我的情况下,验证是一个重要的功能,我需要能够重用。定义一个新变量只是为了让 Typescript 不会抱怨它的类型也感觉很愚蠢,因为在验证之后它只能具有 Variable 类型(代码无法通过 validateVariable(variable) 的行,除非它没有' t 抛出,在这种情况下变量具有适当的类型)。

这样做的好方法是什么?我愿意改变我的代码结构,因为我还在学习很多关于 Typescript 的知识,我对此很灵活!

【问题讨论】:

    标签: typescript types


    【解决方案1】:

    通过给 validateVariable 一个特殊的返回类型,你可以告诉 typescript 如果函数返回(而不是抛出),那么必须定义变量:

    function validateVariable(variable: Variable | undefined): asserts variable is Variable {
      if(!variable) {
        throw new Error('Variable is undefined!')
      }
    }
    

    如果您这样做,那么在您调用 validateVariable(variable) 后,variable 上的类型将缩小为仅 Variable

    Playground link

    【讨论】:

    • 这听起来正是我想要的!我尝试在我的存储库中实现它,我得到了这个:Assertions require every name in the call target to be declared with an explicit type annotation.我错过了什么?
    • 我环顾四周,似乎与我的validateVariable 函数被构建为箭头函数这一事实有关。我可以解决这个问题(无论如何都没有使用“this”),但是有充分的理由为什么它不能与箭头函数一起使用,但它可以与 function 关键字一起使用?
    • 不幸的是,这个功能在 Typescript 3.7 之前似乎不可用,而且我们的存储库仍在 Typescript 3.6.3 上,所以我不能使用它。不过,这似乎是正确的方法。我会给你一张绿色的支票,如果你有比我更好的 Typescript typescriptlang.org/docs/handbook/release-notes/…
    猜你喜欢
    • 2020-01-17
    • 1970-01-01
    • 1970-01-01
    • 2018-06-09
    • 2020-04-02
    • 2020-12-20
    • 2016-08-03
    • 2019-04-10
    • 1970-01-01
    相关资源
    最近更新 更多