never
类型是 TypeScript 对
底部类型 的表示,来自于
类型理论。因此,如果您正在寻找 TypeScript 中
never
的动机和用途,您可能需要研究计算机科学中的底部类型。
"为什么 TypeScript 没有引入 'never' 类型" 的标准回答可能最好通过分析
引入该类型的 pull request 和它解决的两个问题来找到:
请求底部类型和
请求更好地处理无法访问的函数返回。开发人员的主要用途是为不返回任何值的函数(或函数部分)提供类型,甚至不包括 undefined。比较这些函数:"
function u(): undefined {
return;
}
const uRet = u();
console.log(typeof uRet);
function v(): void { }
const vRet = v();
console.log(typeof vRet);
这些函数返回undefined
值:
function throws(): never {
throw new Error();
}
const tRet = throws();
console.log(typeof tRet);
function loops(): never {
while (true) { }
}
const lRet = loops();
console.log(typeof lRet);
由于异常或无限循环而根本不返回值的函数。 never
类型允许开发人员和编译器推断出永远不会运行的代码部分。
除了代码示例,还有其他用途可以使用never
,但我不打算尝试列举它们,因为您已经知道。检查TypeScript标准库以查找never
出现的位置是很有启发性的。
最后,当您提出问题时
大多数示例都显示代码,其中编译器已经推断了never
,那么为什么我还要分配类型?
请注意,即使在编译器为您推断never
的情况下,它在语言中存在也是有用的,就像编译器推断string
时一样有用。这似乎是关于何时需要显式注释类型而不是让编译器推断它们以及反之的不同问题。但是本文已经很长了,这个问题可能已经在其他地方得到了回答。
希望这能帮助您,祝好运!
编辑说明:有很多程序员会使用never
,尽管许多程序员可能永远不需要使用它。让我列举一些我能想到的原因:
If you are writing typings for a JavaScript library where a function throws an exception instead of returning, you can't really do that without never
.
Generic type parameters default to {}
when they can't be inferred by the compiler. It sort of "fails open", since {}
is compatible with (almost) all values. There are cases when you'd prefer it to "fail closed" and have it be compatible with no values. You can use never
as the default parameter.
The union of any type T
with never
is just T
, and the intersection of T
with never
is never
. These rules (among others) let a developer build fairly sophisticated type functions that would be harder or impossible without never
. For example, here's Diff<T,U>
:
type Diff<T extends string, U extends string> =
({ [P in T]: P } & { [P in U]: never } & { [x: string]: never })[T];
It is a type function which takes a union of string literals T
and a union of string literals U
, and returns a union of all the values in T
which are not present in U
.
You can use it to, among other things, remove a property from a type:
type Foo = { a: string, b: number, c: boolean };
type FooWithoutB = Pick<Foo, Diff<keyof Foo, 'b'>>;
这有点像数学中的零。你不{{需要}}它;很多文化没有零的概念也能过得去。但是它非常有用,可以让你轻松表达那些否则会很麻烦甚至不可能实现的想法。希望这样更具吸引力?无论如何,再次祝好运。
never
。我已经编辑了我的答案并列举了其中一些。 - jcalz