TypeScript never 类型

摘要:在本教程中,您将了解 TypeScript 的 never 类型,它用于表示永远不会发生的值。

TypeScript never 类型的介绍

在 TypeScript 中,类型就像一组值。例如,number 类型包含数字 1、2、3 等。string 类型包含字符串,例如 'Hi''Hello' 等。null 类型包含单个值,即 null

never 类型是一种不包含任何值的类型。它就像一个空集

由于 never 类型不包含任何值,因此您无法将值赋给具有 never 类型的变量。

例如,以下操作将导致错误

let empty: never = 'hello';Code language: JavaScript (javascript)

TypeScript 编译器会发出以下错误

Type 'string' is not assignable to type 'never'Code language: JavaScript (javascript)

那么,我们为什么首先需要 never 类型呢?

由于 never 类型的值为零,因此您可以使用它来表示类型系统中的不可能情况。

例如,您可能有一个 交叉类型,它可以同时是字符串和数字,这是不可能的

type Alphanumeric = string & number; // neverCode language: JavaScript (javascript)

因此,TypeScript 编译器将 Alphanumeric 的类型推断为 never

这是因为 stringnumber 是互斥的。换句话说,一个值不能同时是 stringnumber

通常,您使用 never 类型来表示永不将控制权返回给调用者的函数的返回类型。例如,一个总是抛出错误的函数

function raiseError(message: string): never {
    throw new Error(message);
}Code language: TypeScript (typescript)

请不要将其与返回 void 但仍将控制权返回给调用者的函数混淆。

如果您的函数包含无限循环,则其返回类型应为 never。例如

function forever(): never {
  while (true) {}
}Code language: TypeScript (typescript)

在此示例中,forever() 函数的返回类型的类型为 never

TypeScript never 示例

让我们举一个使用 never 类型的例子

type Role = 'admin' | 'user';

const authorize = (role: Role): string => {
  switch (role) {
    case 'admin':
      return 'You can do anything';
    case 'user':
      return 'You can do something';
    default:
      // never reach here util we add a new role
      const _unreachable: never = role;
      throw new Error(`Invalid role: ${_unreachable}`);
  }
};

console.log(authorize('admin'));
Code language: JavaScript (javascript)

它是如何工作的。

步骤 1. 定义一个类型 Role,它可以是字符串 'admin''user'

type Role = 'admin' | 'user';Code language: JavaScript (javascript)

步骤 2. 创建 authorize() 函数,该函数接受 Role 类型的变量并返回一个字符串

const authorize = (role: Role): string => {
  switch (role) {
    case 'admin':
      return 'You can do anything';
    case 'user':
      return 'You can do something';
    default:
      // never reach here util we add a new role
      const _unreachable: never = role;
      throw new Error(`Invalid role: ${_unreachable}`);
  }
};Code language: JavaScript (javascript)

它是如何工作的。

首先,使用 switch 语句在角色为 adminuser 时返回相应的字符串。

其次,定义一个名为 _unreachable 的变量,其类型为 never,并将 role 赋给它。此外,在 default 分支中抛出错误,因为执行永远不会到达 default 分支。

我们为什么要处理 default 案例?

原因是,如果我们向 Role 类型添加新值并忘记添加处理新角色的逻辑,TypeScript 将发出错误

type Role = 'admin' | 'user' | 'guest';Code language: JavaScript (javascript)

在这种情况下,我们将 'guest' 添加到 Role 类型。

TypeScript 会发出以下错误

Type 'string' is not assignable to type 'never'.ts(2322)Code language: JavaScript (javascript)

这是因为 default 分支中角色的值现在变为字符串 'guest',并且您无法将字符串值赋给类型为 never 的变量。

要解决此问题,您需要创建一个新的 case 分支来处理新角色

const authorize = (role: Role): string => {
  switch (role) {
    case 'admin':
      return 'You can do anything';
    case 'user':
      return 'You can do something';
    case 'guest':
      return 'You can do nothing';
    default:
      // never reach here util we add a new role
      const _unreachable: never = role;
      throw new Error(`Invalid role: ${_unreachable}`);
  }
};Code language: JavaScript (javascript)

为了使其更简洁,我们可以定义一个返回类型为 never 的函数,并在 default 分支中使用它

type Role = 'admin' | 'user' | 'guest';

const unknownRole = (role: never): never => {
  throw new Error(`Invalid role: ${role}`);
};

const authorize = (role: Role): string => {
  switch (role) {
    case 'admin':
      return 'You can do anything';
    case 'user':
      return 'You can do something';
    case 'guest':
      return 'You can do nothing';
    default:
      // never reach here util we add a new role
      return unknownRole(role);
  }
};

console.log(authorize('admin'));
Code language: TypeScript (typescript)

总结

  • 使用 never 类型,它不包含任何值,表示类型系统中的不可能情况。
本教程是否有帮助?