TypeScript 联合和交集类型的命名

Naming of TypeScript union and intersection types

提问人:sevcsik 提问时间:8/10/2016 最后编辑:Christopher Peisertsevcsik 更新时间:3/9/2023 访问量:7901

问:

我无法理解 TypeScript 中术语交集类型和联合类型背后的逻辑。我将接口(或类)视为属性集。

逻辑连词算子等价于集合论中的交集,定义为:&

两个集合 A 和 B 的交集,是包含 A 的所有元素的集合,这些元素也属于 B

在 TypeScript 中,Intersection Type 也是使用运算符构建的,其定义如下:&

接口和接口的交集类型是一种新类型,它具有 的所有成员ColorfulCircleColorful Circle

这与数学和集合论中交集的定义完全相反。

我敢肯定还有另一种看待它的方式,但我无法弄清楚。

TypeScript 设置 布尔逻辑

评论

4赞 Lee 8/10/2016
类型的成员是 和 类似的成员是 both 的成员,因此位于 和 的交集中。T | Umembers(T) | members(U)T & UTUmembers(T)members(U)
0赞 Lee 1/14/2020
@jcalz - 我指的是类型的值集,而不是由 定义的成员集。members(T)TT
0赞 jcalz 1/14/2020
嗯,这更有意义!不好意思!
1赞 Changdae Park 2/6/2021
我不能否认命名太糟糕了。他们最好没有名字,而只是解释一下 |表示 either 和 & 表示两者,正如其中一个答案所说。现在我想知道实际的“交叉点”类型在哪里?
1赞 Magne 12/29/2021
∨ := ∪ (union),表示 ,所以 union 是 ,在打字稿中用 表示。voror|

答:

22赞 user663031 8/10/2016 #1

该类型是指 的对象。换言之,这种类型的值是从 的值和 的值的并集中得出的。A | BABAB

该类型指的是同时是 和 的对象。换言之,这种类型的值是从 的值 和 的交集中提取的。A & BABAB

命名和语义在其他语言(如 C++)中是相同的。

评论

0赞 ChrisoLosoph 3/8/2023
为了消除对 OP 的误解:类型需要被视为开放描述(属性的下限),而不是封闭的描述(确切的属性集)。在数学中,类型是一组约束或公式,用于无限多的可能元素可供选择。这就是多态性的起源。元素还可以满足类型中未指定的其他约束。较大的约束集意味着较小的相等元素集可以满足这些约束。 削弱约束。想象一下,将编码集设置为位向量,每个索引代表一个不同的元素。A & BA | B
59赞 Ryan Cavanaugh 8/10/2016 #2

这是另一种思考方式。考虑四组:蓝色事物、红色事物、大事物和小事物。

如果你把所有蓝色事物和所有小事物的集合相交,你最终会得到属性的并集——集合中的所有东西都同时具有蓝色属性和小属性。

但是,如果将蓝色小事物和红色小事物并集在一起,则在结果集合中只有属性是通用的。相交“蓝色小”与“红色小”产生“小”。

换言之,取值域的并集会产生一组相交的属性,反之亦然。

以图像形式:enter image description here

评论

8赞 sevcsik 8/11/2016
谢谢,它非常具有描述性,并且准确地指出了我错的地方:我是在考虑属性集,而不是实例集。
8赞 JoyalToTheWorld 7/13/2017
为什么将类型视为一组实例?实例是什么,类型?什么类型..?这是循环推理,不是吗?
3赞 Ryan Cavanaugh 7/13/2017
将现存的物体分组到命名的分类中(我们现在称之为“类型”)是人类数十万年来一直在做的事情。
4赞 SOFe 4/23/2018
从用户的角度思考,说“A 实现 B 或 C”和“A 同时实现 B 和 C”比“我们确定 A 具有 B 和 C 中的属性”和“A 具有 B 或 C 中的任何属性”更清楚。
1赞 Jon 11/8/2022
“这些集合的并集具有其属性的交集”的说法毫无意义!你也可以说“这些集合的交集具有其属性的交集!这也是事实,也没有携带任何信息。
11赞 Drazen Bjelovuk 3/15/2020 #3

这里的混淆可能源于我们如何想象集合,即认为交集/并集涉及类型的成员,而不是类型本身。我整理了一张图片,希望能澄清这个概念:

Union/Intersection diagram

评论

2赞 Dai 11/25/2021
这个答案并没有真正解释如何或为什么使用显示集合并集的维恩图来描述交集类型(反之亦然)。
0赞 Drazen Bjelovuk 12/1/2021
@Dai 因为联合意味着它可以是 A 对象、B 对象或 AB 对象。如果它是 A 对象,则 B 成员将不存在,反之亦然,因此 A 和 B 都不能保证排他成员。希望这是有道理的。
19赞 Kai Roesner 5/11/2020 #4

在这种情况下,您不能将类型视为对象属性的集合。我们可以通过查看标量变量及其允许值集(而不是对象)来避免对并集和交集类型如何工作的混淆:

type A = 1 | 2
type B = 2 | 3
type I = A & B
type U = A | B

let a: A
let b: B
let i: I
let u: U

a = 1
a = 2
a = 3 // <- error

b = 1 // <- error
b = 2
b = 3

i = 1 // <- error
i = 2
i = 3 // <- error

u = 1
u = 2
u = 3

在这里,术语“并集”和“交集”在应用于允许值的集合时完全对应于集合论项。

将允许值(实例)的概念应用于对象类型有点棘手(因为集合论类比并不成立):

type A = {
  x: number
  y: number
}

type B = {
  y: number
  z: number
}

type I = A & B
type U = A | B
  • 类型的变量可以保存具有属性和(并且没有其他属性)的对象实例。Axy
  • 类型的变量可以保存具有属性和(并且没有其他属性)的对象实例。Byz
  • 在集合论中,上述两组对象意向的交集是空的。但是,交集类型的变量可以保存具有类型属性和类型属性的对象(即 、 和 ;因此是符号),这对应于两种类型属性的并集(因此造成混淆)。IABxyz&
  • 在集合论中,上述两组对象意图的并集不包括具有所有三个属性的对象。但是,联合类型的变量可以保存具有类型属性或类型属性的对象(逻辑 OR,而不是 XOR,即 和 , 和 , 或 , , 和 ;因此符号),这意味着两种类型的属性的集(在我们的示例中)保证存在(因此存在混淆)。UABxyyzxyz|y
let i: I
let u: U

i = { x: 1, y: 2 };         // <- error
i = { y: 2, z: 3 };         // <- error
i = { x: 1, y: 2, z: 3 };

u = { x: 1, y: 2 };
u = { y: 2, z: 3 };
u = { x: 1, y: 2, z: 3 };
3赞 Aliaksandr Adzinets 10/21/2020 #5

我也有同样的问题,不明白怎么能以相反的方式看待它。看完答案后,我想我可以从语言学方面来解释它,提供这两个词的不同含义,并为相反的命名方法留出空间。

比较单词 intersect 的以下含义:

这颗彗星的轨道与地球的轨道相交。

在这句话中,相交的意思是在一个点或一组点上交叉。想想两件事情有共同点(例如一个点),在其他方面是不同的。这就是数学和SQL中所谓的交集

我们需要确定最大可实现的保护与最高潜在经济回报相交的地方。

这里的相交意味着走到一起并相互影响,就像两件事成为一件很酷的新事物的组成部分一样。这就是 TypeScript 中这个词的意思。

以类似的方式,你可以把联合看作是一种在松散的意义上将不同事物连接在一起的行为——这就是联合在数学和SQL中的含义;但它可能不仅意味着加入,而且意味着出于共同的兴趣或目的而结合在一起,这与 TypeScript 中联合的含义相对应。

受到 intersect 俄语的不同翻译的启发(不要问我为什么):пересекать(也杂)和 скрещивать(也杂交)。

-1赞 gedrimas 12/24/2020 #6
type Head = {
  skin: string, 
  bones: string, 
  nouse: number, 
  eyes: number, 
  ears: number 
}

type Body = {
  skin: string, 
  bones: string, 
  arms: number, 
  foots: number
}

type Frankenstein = Head | Body

let frank: Frankenstein

`1 rule (only Head)`

frank = {skin: 'green', bones: 'skull', nouse: 1, eyes: 2, ears: 2}

`2 rule (only Body)`

frank = {skin: 'gray', bones: 'skeleton', arms: 2, foots: 2}

`3 rule (Body and Head all together)`
 
frank = {
  skin: 'green', 
  bones: 'skull', 
  nouse: 1, 
  eyes: 2, 
  ears: 2, 
  arms: 2, 
  foots: 2
}

`4 rule (Frank without arms or foots or ears or ...)`

frank = {
  skin: 'green', 
  bones: 'skull', 
  nouse: 1, 
  eyes: 2, 
  ears: 2,
  foots: 2
 }

frank = {
  skin: 'green', 
  bones: 'skull', 
  nouse: 1, 
  eyes: 2, 
  ears: 2, 
  arms: 2
}

frank = {
  skin: 'green',
  bones: 'skull',
  nouse: 1,
  eyes: 2,
  arms: 2, 
  foots: 2
}

`-1 rule (he can't exist without general parts)`

frank = {
  bones: 'skull',
  nouse: 1,
  eyes: 2,
  ears: 2,
  foots: 2} //error

frank = {
  skin: 'green',
  nouse: 1, 
  eyes: 2,
  ears: 2,
  arms: 2} //error

`-2 rule (and the MOST NOTABLY he can not exist without full kit of one of 
his parts, why - ask his best friend - TypeScript)`

frank = {
  skin: 'green',
  bones: 'skull',
  eyes: 2,
  ears: 2,
  foots: 2} //error

frank = {
  skin: 'green',
  bones: 'skull',
  nouse: 1,
  eyes: 2,
  arms: 2
} //error
3赞 Magne 12/29/2021 #7

他们前几天刚刚更新了文档,现在它用一个简单的例子提供了一个澄清性的描述:

类型联合似乎具有这些类型属性的交集,这可能会令人困惑。这不是偶然的 - 联合这个名字来自类型理论。联合是通过从每种类型中获取值的并集来组成的。请注意,给定两个集合,每个集合都有相应的事实,只有这些事实的交集适用于集合本身的并集。例如,如果我们有一个房间里有戴帽子的高个子,而另一个房间里有戴帽子的讲西班牙语的人,在把这些房间组合起来后,我们对每个人的唯一了解就是他们必须戴帽子。number | string

https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#union-types

1赞 Jorge Garcia 7/27/2022 #8

这样想吧......

交叉点类型(A 和 B)

在物体的宇宙中,只有那些同时与 A B 兼容的对象才属于交集类型的域;因此包含 A 和 B 的所有属性(两组属性的并集)。换句话说,如果对象位于 A 和 B 的交点,它们就拥有 A 和 B 的所有属性(并集)。

联合类型 (A |B)

在对象宇宙中,只有那些与 A B 兼容的对象才属于并集类型的域;因此包含 A 的所有属性或 B 的所有属性,可能在 A 和 B 之间具有某些共同属性或没有共同属性。换句话说,如果对象位于 A 和 B 的集中,它们可以具有 A 的所有属性或 B 的所有属性,以及 A 和 B 的潜在共同属性(交集)。

评论

0赞 Jon 11/8/2022
这没有意义。好的,两个集合的并集包含这两个集合的交集......但是两个集合的交集也包含了这两个集合的交集......因为每个集合都是自己的子集。这就像说;我们把所有生物的集合称为猫,因为这些生物的一个子集是猫。
0赞 Jorge Garcia 11/10/2022
具体来说,什么对你来说没有意义?