- 引用
- 术语
- 死代码(Dead Code)
- never 类型被称为 Bottom Type,是整个类型系统层级中最底层的类型。
- never 类型的类型兼容性
- never 类型的值可以赋值给任何类型
- 只有 never 类型才能赋值给 never 类型
const neverVar = 'never' as unknown as never
const x1: number = neverVar
const x2: string = neverVar
const x3: boolean = neverVar
const x4: symbol = neverVar
const x5: undefined = neverVar
const x6: null = neverVar
const x7: object = neverVar
const x8: any = neverVar
const x9: never = neverVar
// ...
- never 的常见应用场景
- 使用 never 约束函数返回类型
- never 与联合类型结合使用
- 用 never 来约束函数返回类型时,函数体需要满足一定的要求才行,否则会报错
// error
function foo(): never { }
如果将返回类型约束为 never,意味着我们的函数体实现不能乱来,还必须满足一些潜规则才行。
- never 表示永远不会发生,如果你想要表达一个函数执行后将永远不会结束、永远不会有结果、甚至导致程序直接终止运行,那么你可以用 never 来约束函数的返回类型。
- 如果想要表达函数永远不会结束,可以使用 never 类型来约束函数的返回结果
- 一个函数负责抛出错误,你调用它之后,将永远无法拿到该函数的返回值,此时,该函数的返回值类型就可以写作 never
- 一个函数在执行过程中陷入死循环,此时也可以将返回值类型写作 never
function throwError(message: string): never {
throw new Error(message);
}
function infiniteLoop(): never {
while (true) {
// ...
}
}
一些微不足道的细节 死循环中如果出现非 Dead Code 的 break 语句,返回值约束为 never 将会报错。
死循环还必须得使用 true,如果是其它值,比如 1,默认也是不被允许的。
除了支持用 while 表示死循环,ts 也允许我们用 for 来表示死循环。
- 如果一个函数的返回值是 never 类型,那么该函数的调用语句之后的代码将被推断为 Dead Code
function throwError(message: string): never {
throw new Error(message);
}
function foo() {
throwError("undefined error");
// Dead Code
console.log("hello");
console.log("world");
}
Dead Code 表示死代码、无效的代码。在 vscode 中,Dead Code 默认会被置灰,以此来提醒我们这部分的程序很可能是无意义的,它们将永远不会被执行。
- never 表示不应该出现的值,当 ts 判断联合类型中没有其它类型可选时,也会出现 never 类型。
function fn(x: string | number) {
if (typeof x === "string") {
// x: string
} else if (typeof x === "number") {
// x: number
} else {
// x: never
throw new Error(`Unknown input type: ${x}`);
}
}
由于 ts 强大的类型分析能力,每经过一个 if 语句处理,x 的类型分支就会减少一个。在最后的 else 代码块中,它的类型只剩下了 never 类型,即一个无法再细分、本质上并不存在的虚空类型。
- 你可以把 never 视作一个“不存在”的类型
type UnionWithNever = 123 | "abc" | true | void | never;
// 将鼠标悬停在 UnionWithNever 上,查看 ts 推导出来的结果:
// type UnionWithNever = true | void | 123 | "abc"
// 会发现 never 类型直接被无视了
当 never 出现在联合类型中时,它就像一个空集合,不会对联合类型的其他部分产生任何影响。
- 未标明类型的数组,可能会被推断为 never 类型
// 默认配置
const arr = []
// const arr: any[]
// 开启 strictNullChecks 配置,同时禁用 noImplicitAny 配置
const arr = []
// const arr: never[]