TypeScript 调用never 的类型在类型理论中称为bottom type,有时用符号“⊥”表示。这个想法是它是没有该类型值的(唯一)类型。您应该never 发现自己持有该类型的值,因为它没有值。如果您将类型视为可能值的集合,那么它就是empty set(符号“∅”)。
这对你来说可能都是有意义的。
TypeScript 也有subtyping 的概念。就像集合一样,类型可以通过包含一些相同的值来重叠。如果A 类型的每个值也是B 类型的值,那么A 是B 的子类型。你也可以说A 扩展 B,或者象征性地,A <: B。在 TypeScript 中,{a: string} 是 object 的子类型,因为 {a: string} 类型的每个值(例如,{a: "hello"} 的值)也是 object 类型的值。
TypeScript 的可赋值性规则基本与substitutability 有关。如果变量的类型为B 和A <: B,则可以为该变量分配A 类型的值,因为A 类型的每个值也是B 类型的值。您不一定要反过来,将B 类型的值分配给A 类型的变量。除非B <: A,否则有一些B 类型的值不是A 类型的值。
从作为值集的类型的角度来看,A <: B 就像是说A 类型的值集是subset 类型的值集B 的一个subset,(符号A ⊆ B)。
这可能(我希望)对你也有意义。
我们还需要一件事:逻辑 principle of explosion。如果您从一个错误的陈述开始,那么您可以从中证明任何东西。所以,假设“月亮是奶酪做的”是假的,那么“如果月亮是奶酪做的,那么今天就是星期三”是真的。此外,“如果月亮是奶酪做的,那么今天就不是星期三”是真的。把假的东西当真会产生可怕的后果:一切都会爆炸。 ? 这可能令人惊讶,但这是条件语句与其contrapositive 等价的直接结果。你可能对“如果今天不是星期三,那么月亮不是由奶酪制成的”和“如果今天是星期三,那么月亮不是由奶酪制成的”这句话或它们组合成“月亮不是由奶酪制成”感到满意奶酪,不管今天是什么日子”。
如果您不接受爆炸原理(许多数学家和逻辑学家也有同样的感受),那么接下来的内容可能对您不利。但至少要意识到爆炸的原理与形式逻辑和 TypeScript 中使用的类型理论是一致的。它具有有用的结果,弥补了它的怪异。
现在让我们把所有这些放在一起。让我们随机选择一个类型T,并提出问题:never <: T?这相当于问题“never 类型的每个值也是T 类型的值吗?”或者,以下陈述是否适用于所有值 x:“如果 x 是 never 类型的值,那么它也是 T 类型的值”?根据never 的定义,我们知道“x 是never 类型的值”必须始终为false。并且根据爆炸原理,“如果x 是never 类型的值,那么x 是T 类型的值”语句必须始终为true。因此,never <: T 对于任何T 都是true。即使您有两种类型 X 和 Y,它们完全互补并且不包含共同的值,never <: X 和 never <: Y 都是正确的。
在集合论的术语中,它基本上是说空集是每个集合的子集。也就是说,∅ ⊆ T 表示任何 T。这是集合论中完全没有争议的陈述,但可能会给您同样的错误感。在任何情况下,你永远不会找到一个既不是集合T 的元素的空集合元素。
因此never 类型的值始终可以分配给任何其他类型的任何变量。幸运的是,实际上,在运行时,您不会有任何 never 类型的值。但是 TypeScript 允许赋值,因为它是类型安全的并且有一些有用的结果。
请注意,您不能说反话。 T <: never 不是真的,除非 T 是 never 本身。 string 类型的值不能分配给never 类型的变量,因为没有string 值也是never 值。随心所欲的可分配性规则只有一个方向。
好的,我希望这是有道理的。我想继续讨论类型理论中的top type 以及它最近作为unknown 包含在TypeScript 中,以及它如何补充never,但如果我这样做,这个答案将是一本教科书。所以我现在就停下来。
希望对您有所帮助。祝你好运!