JavaScript 和 TypeScript 中的 void

404 阅读2分钟

原文:fettblog.eu/void-in-jav…
译文:涂鸦码龙

如果写过强类型语言,会比较熟悉 void 的概念:调用函数和方法的时候,什么也不返回。

JavaScript 中的 void 是操作符,TypeScript 中的 void 是基本类型。void 在两个环境中的表现有所不同。

JavaScript 中的 void

JavaScript 中的 void 是操作符,可以执行表达式。不关心表达式执行结果,void 总是返回 undefined

let i = void 2; // i === undefined

那为什么需要它呢?首先,早期我们可以覆盖 undefined,给出确切的值。void 总是返回真正的 undefined

其次,它是调用立即执行函数的好法子:

void function() {
  console.log('What')
}()

不会污染全局命名空间:

void function aRecursion(i) {
  if(i > 0) {
    console.log(i--)
    aRecursion(i)
  }
}(3)

console.log(typeof aRecursion) // undefined

由于 void 总是返回 undefinedvoid 总会执行紧随其后的表达式,有一个很便利的方法可以做到,函数没有返回任何值,但是仍然调用了 callback:

// 返回其它值,app 会崩溃
function middleware(nextCallback) {
  if(conditionApplies()) {
    return void nextCallback();
  }
}

对我而言,void 最重要的作用是 app 的保安闸。既然函数默认返回 undefined,我们也可以明确地定义它。

button.onclick = () => void doSomething();

TypeScript 中的 void

TypeScript 中的 voidundefined 的子类型。JavaScript 中的函数总会返回一个值,或者 undefined

function iHaveNoReturnValue(i) {
  console.log(i)
} // 返回 undefined

没有返回值的函数总是返回 undefined,JavaScript 中的 void 总是返回 undefined,TypeScript 中的 void 是个合适的类型,表明函数返回 undefined

declare function iHaveNoReturnValue(i: number): void

void 可以用于参数或者其他的声明,只有 undefined 可以传:

declare function iTakeNoParameters(x: void): void

iTakeNoParameters() // 👍
iTakeNoParameters(undefined) // 👍
iTakeNoParameters(void 2) // 👍

所以 voidundefined 几乎一样。有一点点不同的是:void 作为返回类型,可以用不同的类型替代,允许高级回调模式:

function doSomething(callback: () => void) {
  let c = callback() // 此处,callback 总是返回 undefined
  // c 也是 undefiend 类型
}

// 函数返回 number 类型
function aNumberCallback(): number {
  return 2;
}

// 👍 类型安全在 doSometing 中得到保证
doSomething(aNumberCallback) 

这种期望的行为常用于 JavaScript 应用。可置换性的模式可以阅读我的其他文章。

如果想确保传入的函数只返回 undefined,需要修改 callback 的类型定义:

- function doSomething(callback: () => void) {
+ function doSomething(callback: () => undefined) { /* ... */ }

function aNumberCallback(): number { return 2; }

// 💥 类型不匹配
doSomething(aNumberCallback)