【问题标题】:Is it OK to cast undefined to void in TS?可以在 TS 中将 undefined 强制转换为 void 吗?
【发布时间】:2020-06-27 06:02:33
【问题描述】:

TLDR;

这样可以吗?或者这是不好的做法?

function isUndefined (payload: any): payload is undefined | void {
  return payload === undefined
}

上下文

在 TypeScript 中,我有一个函数可以返回一些东西或 undefinedvoid

类似于可以返回修改后的有效负载的事件处理程序,或者开发人员可以选择不返回任何内容或未定义,以防他们不会修改有效负载:

function eventHandler <T extends {[key: string]: any}> (payload: T): Modified<T> | undefined | void {
  // ... implementation
}

然后我有一个类型检查器,它需要检查它是否返回 void 或 undefined 以外的东西:

const result = eventHandler(payload)

if (result !== undefined) {
  // we have a modified payload!
}

但是,上面的 sn-p 是否会出现错误,因为它说即使 result !== undefined 它仍然可以是 void

在我看来,我认为这很奇怪,因为void 应该与undefined 相同。

所以我做了这个类型检查器来解决它:

function isUndefined (payload: any): payload is undefined | void {
  return payload === undefined
}

这解决了我的问题,但我的问题是:

这样好吗?还是不好的做法?

【问题讨论】:

    标签: javascript typescript casting void void-safety


    【解决方案1】:

    void 不是undefinedvoid 表示没有返回值。 undefined 是运行时未定义的值的类型。

    确实,在运行时不返回值的函数会返回undefined,但在 TS 类型系统中,我们选择让没有返回值变得特殊。

    例如分配(a) =&gt; void to (a) =&gt; number | undefined 可能是一个错误,尽管它在运行时是安全的。

    一般不要在函数的返回类型中使用 void。对于其他所有内容,请使用undefined

    所以,是的,我们需要对 undefinedvoid 使用不同的检查。

    【讨论】:

      【解决方案2】:

      我认为你让事情变得更复杂了。返回void 的函数可以:

      1. 没有返回语句
      2. 有一个没有指定值的return; 语句。
      3. 有一个return undefined; 声明。

      在纯 javascript 中,以上所有内容的返回值都是 undefined。如果你说一个函数返回undefined,那么你只能做上面列表中的#2和#3。

      所以你可以有一个函数类型,将void 与你想要的任何东西联合起来。

      function foo(): string | void {
          return Math.random() > 0.5 ? 'abc' : 123
      }
      
      const val = foo()
      if (val === undefined) {
          console.log('is undefined', val)
      } else {
          console.log('is some value', val)
      }
      

      这意味着您可以创建一个通用函数类型来修改有效负载,如下所示:

      type PayloadModifier<T extends {[key: string]: any}> = (payload: T) => T | void
      
      const setMaxAsTen: PayloadModifier<{a: number}> = (payload) => {
          if (payload.a > 10) {
              return { a: 10 }
          }
          return undefined // required unless noImplicitReturns is false
      }
      
      const val = setMaxAsTen({a: 5})
      if (val === undefined) {
          console.log('is undefined', val)
      } else {
          console.log('is some value', val)
      }
      

      Playground

      最后要注意的是,有一个编译器选项可以保留在called noImplicitReturns 上。如果函数在任何执行分支中声明返回值,则必须在每个执行分支中声明返回值。因此,由于上述内容有时会返回一个值,因此如果您不返回有效负载,则必须显式返回 undefined。您可以关闭该选项,允许您省略该行,但不建议这样做,因为它确实可以帮助您捕获一些错误。

      【讨论】:

        猜你喜欢
        • 2011-06-17
        • 1970-01-01
        • 2012-04-12
        • 2015-08-08
        • 1970-01-01
        • 2016-05-01
        • 1970-01-01
        • 2023-03-27
        • 1970-01-01
        相关资源
        最近更新 更多