为什么类型“从不"?在联合类型中毫无意义? [英] Why is the type "never" meaningless in union types?

查看:23
本文介绍了为什么类型“从不"?在联合类型中毫无意义?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

但是在联合类型中,我的直觉最初告诉我never类型将是一个有效的选择.我的问题是为什么不是?为什么 never 可以在联合类型中被丢弃?

有人可以对此做出合理的解释,以便我更好地理解吗?

解决方案

将类型视为 set 可分配给它的所有值.所以 boolean 可以被认为是 {true, false},只包含这两个值的集合.而 string 可以被认为是(本质上)包含每个可能的 string 值的无限集合.

在 TypeScript 中,never底部类型.它有没有值.如果您有一个 JavaScript 值并且您问这是 never 类型的值吗?"那么答案是否".就集合而言,never 可以被认为是∅,即空集.

在从类型到值集的映射中,intersection 操作可以被认为是 设置交集操作(∩).如果你有集合 A 和 B,那么 A∩B 是恰好属于 两者 A B 的对象的集合.对于任何集合 A,交集 A带有空集的∩∅就是空集∅.A 和空集中都没有元素,因为空集中根本没有元素.回到 TypeScript 类型,这意味着 A &对于任何类型 A,从不 变为 从不.如果 TypeScript 编译器只留下 string &从不 as string &从不,但实际上它会自动将其缩减为从不,因为后者表示更简单.

另一方面:在从类型到值集的映射中,union 操作在 TypeScript (|) 中可以被认为是 设置并集 操作(∪).如果你有集合 A 和 B,那么 A∪B 是恰好属于 a B 成员的对象的集合(这是一个inclusive 或).对于任何集合 A,具有空集的并集 A∪∅ 就是 A.该并集包含 A 的所有元素和空集的所有元素.由于没有空集的元素,所以它只是A 的所有元素".回到 TypeScript 类型,这意味着 A |对于任何类型的 A,从不 变为 A.如果 TypeScript 编译器只留下 string | 则是有效的.从不 as string |从不,但实际上它会自动将其缩减为string,因为后者表示更简单.

这就是基本的解释.还有其他类比,例如布尔逻辑命题,例如此元素是此类型的成员";对于 never 类型总是 FALSE,导致类似 A ∧ FALSE = FALSE 和 A ∨ FALSE = A 的结果.union 看起来像加法(这个类比对于对而不是交集和有区别的联合而不是常规联合变得准确)并且 never 类型是 0.但希望这能提供足够的直觉来解释编译器为什么会这样.

请注意,TypeScript 中还有一个名为 unknown顶级类型它的行为与 never 中的对偶完全相同,A &未知 = AA |未知 = 未知 并且在集合论中具有双重模拟(通用集合/类).但是你没有问这个问题,这个答案已经足够长了.

Typescript playground

I'm having some trouble while trying to wrap my head around the fact that the type never is meaningless and can be discarded when it's inside a union type.

I mean, I get that inside an intersection type, never will immediately make everything result in never, since no type can by some type and never at the same type. It makes sense to me.

But in an union type, my instinct initially tells me that the never type would be a valid option. My question is why isn't it? Why does never can be discarded in a union type?

Could anybody give a reasonable explanation about this so I can understand it better?

解决方案

One way to think of a type is as a set of all the values that are assignable to it. So boolean can be thought of as {true, false}, the set containing just those two values. And string can be thought of as the (essentially) infinite set containing every possible string value.

In TypeScript, never is the bottom type. It has no values. If you have a JavaScript value and you ask "is this a value of type never?" then the answer is "no". In terms of sets, never can be thought of as ∅, the empty set.

In the mapping from types to sets-of-values, the intersection operation in TypeScript (&) can be thought of as the set intersection operation (∩). If you have sets A and B, then A∩B is the set of exactly the objects which are members of both A and B. For any set A, the intersection A∩∅ with the empty set is just the empty set ∅. There are no elements in both A and the empty set, since there are no elements in the empty set at all. Back in TypeScript types, this means A & never becomes never for any type A. It would be valid if the TypeScript compiler just left string & never as string & never, but in fact it goes ahead and reduces it to never automatically, since the latter representation is simpler.

On the flip side: in the mapping from types to sets-of-values, the union operation in TypeScript (|) can be thought of as the set union operation (∪). If you have sets A and B, then A∪B is the set of exactly the objects which are members of either A or B (this is an inclusive or). For any set A, the union A∪∅ with the empty set is just the A. The union contains all the elements of A and all the elements of the empty set. Since there are no elements of the empty set, that's just "all the elements of A". Back in TypeScript types, this means A | never becomes A for any type A. It would be valid if the TypeScript compiler just left string | never as string | never, but in fact it goes ahead and reduces it to string automatically, since the latter representation is simpler.

So that's the basic explanation. There are other analogies, such as boolean logic propositions like "this element is a member of this type" which is always FALSE for the never type, leading to things like A ∧ FALSE = FALSE and A ∨ FALSE = A. Or like arithmetic, where the analogy isn't exact, but intersection looks like multiplication and union looks like addition (this analogy becomes exact for pairs instead of intersection and discriminated unions instead of regular unions) and the never type is 0. But hopefully this gives enough intuition about why the compiler behaves this way.

Note that there's also a top type in TypeScript called unknown which behaves exactly as the dual to never in that A & unknown = A and A | unknown = unknown and has the dual analog in set theory (the universal set/class). But you didn't ask about that and this answer is already long enough as it is.

这篇关于为什么类型“从不"?在联合类型中毫无意义?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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