TypeScript文档说
该
never类型是每种类型的子类型,并且可以分配给每种类型
但没有提及原因。
凭直觉,我希望这样的代码会失败:
const useString = (str: string) => console.log('This is definitely a string:', str)
const useNever = (not_a_string: never) => useString(not_a_string)
Run Code Online (Sandbox Code Playgroud)
但没有错误,因为任何never值都被视为有效字符串。
这是故意的吗?如果是,那为什么呢?:)
TypeScript调用的类型never在类型理论中称为底部类型,有时用符号“?”来表示。这个想法是它是(唯一)类型,没有该类型的值。您应该never发现自己拥有该类型的值,因为它没有值。如果将类型视为可能的值的集合,则它是空集合(符号“?”)。
这可能对您来说很有意义。
打字稿也有概念亚型。就像集合一样,类型可以通过包含一些相同的值来重叠。如果类型的每个值A也是类型的值B,然后A是一个亚型的B。您也可以说A 扩展 B或象征性地 A <: B。在TypeScript中,{a: string}是的子类型object,因为type的每个值{a: string}(例如value {a: "hello"})也是type的值object。
TypeScript的可分配性规则基本上与可替换性有关。如果变量的类型为B和A <: B,则可以为该A变量分配类型的值,因为每个类型A的值也是类型的值B。您不必执行相反的操作,B即将type的值分配给type 的变量A。除非B <: A某些类型的值B不是类型的值A。
从值的类型集的角度来看,A <: B就像说类型的值集是类型的值集(符号)A的子集。BA ? B
这(我希望)对您来说也很有意义。
我们还需要做一件事:爆炸的逻辑原理。如果您从一个错误的陈述开始,那么您可以从中证明一切。因此,假设“月亮是由奶酪制成”是错误的,那么“如果月亮是由奶酪制成,那么今天是星期三”是正确的。同样,“如果月亮是用奶酪制成的,那么今天不是星期三”。采取虚假的说法会带来可怕的后果:一切都会爆炸。这可能令人惊讶,但这是条件语句与其对立等价的直接结果。。您可能会对以下句子感到满意:“如果今天不是星期三,那么月亮不是由奶酪制成的”和“如果今天不是星期三,那么月亮不是由奶酪制成的”,或者将它们组合成“月亮不是由奶酪制成”无论今天是星期几”。
如果您不接受爆炸原理(许多数学家和逻辑学家也有同样的想法),那么接下来的事情可能对您来说就不那么好了。但是至少要意识到爆炸的原理与TypeScript中使用的形式逻辑和类型理论是一致的。它具有有用的结果,弥补了它的怪异。
现在,让我们将所有这些放在一起。让我们T随机选择一个类型,然后问一个问题:是never <: T吗?这相当于这个问题:“是类型的每个值never 也类型的值T?” 或者,以下语句是否适用于所有值x:“如果x是type的值never,那么它也是type的值T”?根据的定义never,我们知道“ x是类型的值never”必须始终为false。根据爆炸原理,“如果x是类型的值never,那么x是类型的值”的陈述T必须始终为true。因此,never <: T是真正的任何T。即使您有两个类型X和Y,它们是完全互补的并且不包含任何共同的值,never <: X并且never <: Y都是正确的。
用集合论的术语来说,基本上是说空集合是每个集合的子集。也就是说,? ? T对于任何T。在集合论中,这是完全没有争议的陈述,但可能会给您同样的错误感。无论如何,您永远找不到空集合的元素,该元素也不是集合的元素T。
因此,never可以始终将类型的值分配给任何其他类型的任何变量。幸运的是,实际上,在运行时,您将没有type的任何值never。但是TypeScript允许分配,因为它是类型安全的,并且会带来一些有用的后果。
请注意,您不能说相反的话。 T <: never除非T它never本身是不正确的。类型值string不能分配给类型变量never,因为没有string值也是never值。万事俱备的可分配性规则仅在一个方向上。
好吧,我希望这是有道理的。我想继续探讨类型理论中的顶级类型,以及它最近在TypeScript中作为包含在内unknown,以及它如何对互补never,但是如果我这样做的话,这个答案将是一本教科书。所以我现在停止。
希望对您有帮助。祝好运!
| 归档时间: |
|
| 查看次数: |
165 次 |
| 最近记录: |