与我交流
与我交流

Never

程序语言的设计确实应该存在一个底部类型的概念,当你在分析代码流的时候,这会是一个理所当然存在的类型。TypeScript 就是这样一种分析代码流的语言(😎),因此它需要一个可靠的,代表永远不会发生的类型。

never 类型是 TypeScript 中的底层类型。它自然被分配的一些例子:

  • 一个从来不会有返回值的函数(如:如果函数内含有 while(true) {});
  • 一个总是会抛出错误的函数(如:function foo() { throw new Error('Not Implemented') }foo 的返回类型是 never);

你也可以将它用做类型注解:

let foo: never; // ok

但是,never 类型仅能被赋值给另外一个 never

let foo: never = 123; // Error: number 类型不能赋值给 never 类型

// ok, 做为函数返回类型的 never
let bar: never = (() => {
  throw new Error('Throw my hands in the air like I just dont care');
})();

很棒,现在让我们看看它的关键用例。

用例:详细的检查

function foo(x: string | number): boolean {
  if (typeof x === 'string') {
    return true;
  } else if (typeof x === 'number') {
    return false;
  }

  // 如果不是一个 never 类型,这会报错:
  // - 不是所有条件都有返回值 (严格模式下)
  // - 或者检查到无法访问的代码
  // 但是由于 TypeScript 理解 `fail` 函数返回为 `never` 类型
  // 它可以让你调用它,因为你可能会在运行时用它来做安全或者详细的检查。
  return fail('Unexhaustive');
}

function fail(message: string): never {
  throw new Error(message);
}

never 仅能被赋值给另外一个 never 类型,因此你可以用它来进行编译时的全面的检查,我们将会在辨析联合类型中讲解它。

void 的差异

一旦有人告诉你,never 表示一个从来不会优雅的返回的函数时,你可能马上就会想到与此类似的 void,然而实际上,void 表示没有任何类型,never 表示永远不存在的值的类型。

当一个函数没有返回值时,它返回了一个 void 类型,但是,当一个函数根本就没有返回值时(或者总是抛出错误),它返回了一个 nevervoid 指可以被赋值的类型(在 strictNullChecking 为 false 时),但是 never 不能赋值给其他任何类型,除了 never