为什么在 TypeScript 中引入了 `never` 类型? [英] Why was the `never` type introduced in TypeScript?

查看:25
本文介绍了为什么在 TypeScript 中引入了 `never` 类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我现在已经在互联网上搜索了为什么引入 never 类型的解释.TypeScript 手册和 TypeScript Deep Dive 都解释了它是什么以及其他一些文章.但是,他们都没有解释为什么要使用 never 类型以及它解决了什么问题.大多数示例显示代码,其中编译器已经推断 never,那么为什么我必须分配类型?它解决什么问题.是否只是"向智能感知发出信号我之后可以做什么(即什么都没有 - 这可能足够有用).编译器使用这些信息做什么?与往常一样,对什么"和如何做"的解释可能会帮助人们做事,但只有为什么"才能让他们理解.

I have now searched the internet for an explanation of WHY the never type was introduced. Both the TypeScript handbook and the TypeScript Deep Dive exaplains what it is and a few other articles. None of them explains, though, WHY you would use the never type and what it solves. Most of the examples show code, where the compiler already infers never, so why do I have to assign the type? What does it solve. Is it "just" to signal the intellisense what I can do afterwards (i.e. Nothing - which might be useful enough). And what do the compiler use the information for? As always, explanations of WHAT and HOW might help people do stuff, but only WHY makes them understand.

推荐答案

never 类型是 TypeScript 对 底部类型来自类型理论.因此,如果您正在寻找在 TypeScript 中 never 的动机和用途,您可能需要查看一般计算机科学中的底层类型.

The never type is TypeScript's representation of the bottom type from type theory. So if you are looking for motivation for and uses of never in TypeScript, you might want to look into the bottom type in computer science in general.

为什么 never 被引入 TypeScript"的规范答案可能最好通过分析 引入它的拉取请求及其解决的两个问题:请求底部类型,以及请求更好地处理无法访问的函数返回.

The canonical answer to "why was never introduced to TypeScript" is probably best found by analyzing the commentary on the pull request that introduced it and the two issues that it addresses: a request for a bottom type, and request to better handle unreachable function returns.

开发人员的主要用途是为函数(或函数的部分)提供一种根本不返回任何值的类型,甚至不返回undefined.比较这些功能:

The main use for developers is to have a type for functions (or sections of functions) that don't return any value at all, not even undefined. Compare these functions:

function u(): undefined {
    return;
}
const uRet = u();
console.log(typeof uRet); // undefined

function v(): void { }
const vRet = v();
console.log(typeof vRet); // undefined

返回 undefined 值,使用这些函数:

which return undefined values, with these functions:

function throws(): never {
    throw new Error();
}
const tRet = throws();
console.log(typeof tRet); // does not run

function loops(): never {
    while (true) { }
}
const lRet = loops();
console.log(typeof lRet); // does not run

由于异常或无限循环,根本不返回值.never 类型允许开发人员和编译器对永远无法运行的代码部分进行推理.

which don't return values at all, due to an exception or an infinite loop. The never type allows both developers and the compiler to reason about sections of code which can never run.

never 还有其他用途,但我不会尝试枚举它们,因为您已经知道代码示例.检查 TypeScript 标准库 以找到<代码>从不出现.

There are other uses for never but I am not going to try to enumerate them, since you already are aware of code examples. It is illuminating to examine the TypeScript standard library to find the places where never shows up.

最后,当你问

大多数示例显示代码,其中编译器已经推断never,那么为什么我必须分配类型?

Most of the examples show code, where the compiler already infers never, so why do I have to assign the type?

请注意,即使在编译器为您推断 never 的情况下,它存在于语言中也是有用的,就像 string 甚至有用一样当它被编译器推断出来时.这似乎是一个关于何时可能想要显式注释类型而不是让编译器推断它们的不同问题,反之亦然.但是这篇文章已经很长了,这可能在别处回答.

note that even in cases where the compiler infers never for you, it is useful for it to exist in the language, in the same way that string is useful even when it is inferred by the compiler. This seems like a different question about when you might want to explicitly annotate types instead of letting the compiler infer them, and vice versa. But this post is already long and this is probably answered elsewhere.

希望有所帮助;祝你好运!

Hope that helps; good luck!

程序员使用从不的原因有很多,尽管许多程序员可能永远不需要使用它.让我列举一些我能想到的原因:

There are plenty of reasons a programmer would use never, although many programmers might never need to use it. Let me enumerate some reasons I can think of:

  • 如果您正在为 JavaScript 库编写类型,其中函数抛出异常而不是返回,那么如果没有 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.

当编译器无法推断时,泛型类型参数默认为 {}.它有点打开失败",因为 {} 与(几乎)所有值兼容.在某些情况下,您希望它失败关闭"并且不兼容任何值.您可以使用 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.

任何类型Tnever的并集就是T,以及T的交集> 使用 nevernever.这些规则(以及其他规则)让开发人员构建相当复杂的类型函数,如果没有never,这些函数将变得更加困难或不可能.例如,这里是 Diff:

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];

它是一个类型函数,它接受字符串文字的联合T和字符串文字的联合U,并返回中所有值的联合U 中不存在的 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'>>;
// equivalent to { a: string, c: boolean }

这有点像数学中的数字零.你不需要;许多文化在没有零概念的情况下相处得很好.但它非常有用,可以让您轻松表达否则会很麻烦或不可能的想法.

It's kind of like the number zero in mathematics. You don't need it; many cultures got along okay without the concept of zero. But it's incredibly useful and allows you to easily express ideas that would otherwise be cumbersome or impossible.

希望这更引人注目?不管怎样,再次祝你好运.

Hopefully that is a little more compelling? Anyway, good luck again.

这篇关于为什么在 TypeScript 中引入了 `never` 类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆