Typescript:交叉类型 - 对命名感到困惑

7

我对Typescript中交叉类型的名称有些困惑。

在集合论中,交集意味着两种类型之间只有共同的属性才会在它们的交集中可用。

事实上,如果我在基本类型之间创建交集,Typescript就是这样行事的。

type A = string | number
type B = number | boolean
type C = A & B

type D = string
type E = number
type F = D & B

在这种情况下,TS 推断 CnumberFnever

enter image description hereenter image description here

然而,当涉及到对象时,创建交集会创建一个新的类型/接口,结合了所使用类型的属性 -

enter image description hereenter image description here

从文档中可以得知:

TypeScript 提供了另一种称为交叉类型的结构,主要用于组合现有的对象类型

当您以这种方式查看对象的行为时,使用 & 也是有道理的。

那么,我的问题如下:

  1. 为什么对象和基本类型的行为看起来不同?
  2. 为什么选择了交叉的名称?

也许这与 联合类型 的解释有关?

enter image description here


对象不是行类型吗?也就是说,如果某个东西是ObA,那么它就有一个名称和一个onlyA(可能还有其他属性),ObB也是如此。这意味着,如果某个东西既是ObA又是ObB,那么它必须具有名称、onlyA和onlyB。原始数据类型的工作方式不同,因为它们不是行类型——整数只是整数,它不能既是整数又是带有名称的东西。 - jlwoodwa
1个回答

6
两个集合的交集是指共有的元素。
类型只是对值集合的描述。
所以对于原始类型“字符串和数字”的交集,哪个值同时属于“字符串”集和“数字”集,即可以同时是“字符串”和“数字”。答案是没有这样的值。因此我们得到“never”(空集)。
对于对象类型,结果有所不同。对象类型描述了集合,其中的值必须至少具有类型所描述的属性。因此,在集合 { name: string, onlyA: string[] } 中的值可能具有属性 onlyB,但它们不一定必须具有该属性(参见 示例)。
回到交集 “ObA&ObB”,此交集中的值必须同时满足“ObA”和“ObB”的描述。因此,该集合中的值将是来自 ObA 的具有 onlyB 属性的值,以及来自 ObB 的具有 onlyA 属性的值。基本上,这些值满足两个集合描述,与原始类型不同,我们可以通过创建具有两种类型属性的对象来构造对象类型的交集。
我的 tsconf 制作坊 从“类型为集合”一节开始,您可能会觉得有趣。

这使得清晰明了:> 这个交集中的值必须同时满足ObA和ObB的描述。 - sarincasm
然而,我不确定这是否正确:对象类型描述值必须至少具有类型所描述的属性的集合。因此,集合 { name: string, onlyA: string[] } 中的值可以具有属性 onlyB,但不需要具有它。如果我尝试将 onlyB 添加到类型为 obA 的对象中,则 TS 会给出错误。https://www.typescriptlang.org/play?#code/C4TwDgpgBAglC8UDOwBOBLAdgcygHykwFcBbAIwlQFgAoUSKAIQUNItXyjIHtuAbCAENMtetADCLOADImtUeGgARFigw4FDAKIti5SpugAxFitmN5dRVADyZOIgDetAJCZBJCAC5kaLNlduTD4QGB81fwBtAF1aAF9aAGMglChBQR87ByhnGjcPbygAcgALdCKAGkDg0J9I0qLoqryyn1Ly+NogA - sarincasm
1
@Eels 这被称为过度属性检查,只会在一种非常特殊的情况下发生,即当您将对象文字分配给已定义类型的变量时。它旨在防止常见错误,但确实违反了正常的子类型规则。如果您经过额外的变量,则不再出现此错误(如我在示例中所示)。 - Titian Cernicova-Dragomir
所以,“因此,此集合中的值将是具有onlyB属性的ObA中的值,以及具有onlyA属性的ObB中的值”是并集的确切定义。因此,我认为对于基本类型,交集确实起作用,但对于对象类型A | B = > OR A OR B,A&B = >单个对象中字段的联合。 - fake364

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接