4

TLDR;

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

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

语境

在 TypeScript 中,我有一个函数可以返回 something 或undefinedor void

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

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!
}

但是,上面的代码片段是否会出现错误,因为它说即使result !== undefined它仍然可以void

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

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

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

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

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

4

2 回答 2

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)
}

操场

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

于 2020-03-16T06:30:16.677 回答
1

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

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

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

通常不要使用 void,除非在函数的返回类型中。对于其他所有内容,请使用undefined.

所以,是的,我们需要对undefined和使用不同的检查void

于 2020-03-16T06:27:46.823 回答