摘要:在本教程中,您将了解 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; // never
Code language: JavaScript (javascript)
因此,TypeScript 编译器将 Alphanumeric
的类型推断为 never
。
这是因为 string
和 number
是互斥的。换句话说,一个值不能同时是 string
和 number
。
通常,您使用 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 语句在角色为 admin
或 user
时返回相应的字符串。
其次,定义一个名为 _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
类型,它不包含任何值,表示类型系统中的不可能情况。