void

对于 TypeScript 中的其它基本类型如 number string boolean 都很好理解,void 的用法就有点特别。 我们最常见的就是在一个不返回任何值的函数中,它的返回类型会被推断为 void

const f = () => {
  console.log('return nothing')
}
const v = f(); // inferred v: void

简单地说: void 表示不返回任何东西。我们可以把 void 看作是 any 的相反类型,因为 any 表示可以任何类型值。

虽然它也是一个类型,但在 TS 中给一个变量显式定义 void 类型是没有任何意义的,这样的话我们只能给该变量赋值为 undefined 或者 null (关闭 —strictNullChecks 的情况下),正如我们通常也不会特意去定义一个变量为 undefined

let a: void = undefined; // no need.
a = null; // if --strictNullChecks disabled.

JavaScript 中,没有显式返回任何值的函数默认返回 undefined ,这样正好跟只有 undefined 才能赋值给 void 类型的规则契合。

使用 void 类型

前面说通常不会显式给一个变量定义 void 类型,在某些情况下手动指定 void 类型还是有用的,比如对于 this 值。

对于TypeScript 中的函数或者方法的 this ,它的默认类型都是 any ,从 TypeScript 2.0 开始,我们可以显式指定 this 的类型,它作为一个伪参数出现在函数参数列表的第一位:

function f(this:void) {
  this.o = 0; // Property 'o' does not exist on type 'void'.
}

在一个全局定义的独立函数中,它的 this 值默认值是 global ,在这个函数内使用 this 是没有任何意义的,所以我们可以显式定义 this: void 表示这里不需要使用 this

来看一个更具体一点的例子

// come from typescript release note.

interface UIElement {
    addClickListener(onclick: (this: void, e: Event) => void): void;
}

class Handler {
    info: string;
    onClickBad(this: Handler, e: Event) {
        // oops, used `this` here. using this callback would crash at runtime
        this.info = e.message;
    }
}
let h = new Handler();
uiElement.addClickListener(h.onClickBad); // error!

在上面的这里例子中,调用 addClickListener 方法的是 UIElement 的实例,它的 this 值指向的是该实例,而 onclick 方法作为一个回调函数传进来,会丢失它自身真正的 this ,所以在 onclick 的类型定义中显式把 this 定义为 void ,告诉使用者不能在传给 addClickListener 的回调函数中使用 this,否则会报错。