A | B
类型表示的是对象可以是A
或者B
中的任意一种。换句话说,这种类型的值来自于A
和B
的值的并集
A & B
类型表示的是对象同时是A
和B
中的两种。换句话说,这种类型的值来自于A
和B
的值的交集
在其他语言如C++中,命名和语义是相同的。
在这种情况下,你不能把类型看作对象属性的集合。我们可以通过查看标量变量及其可允许值的集合(而不是对象)来避免有关联合和交叉类型如何工作的混淆:
查看此处的标量变量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
A
的变量可以存储具有属性 x
和 y
(但没有其他属性)的对象实例。B
的变量可以存储具有属性 y
和 z
(但没有其他属性)的对象实例。I
的交集类型变量可以存储既具有类型A
的属性又具有类型B
的属性(即 x
、y
和 z
;因此使用了 &
符号),这对应于两种类型属性的并集(因此导致混淆)。U
的并集类型变量可以存储具有类型A
的属性或具有类型B
的属性的对象(逻辑上的OR,而不是XOR,即 x
和y
,y
和z
,或 x
、y
和 z
;因此使用了 |
符号),这意味着两种类型属性的交集(在我们的示例中是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 };
我也有同样的问题,不明白如何以相反的方式看待它。读完答案后,我想我可以从语言角度解释它,提供两个词的不同含义,并为相反的命名方法留下空间。
比较单词intersect的以下含义:
这颗彗星的轨道与地球的轨道相交。
在这个句子中,intersect的意思是在一个点或一组点相交。想象两个事物有某些共同之处(例如一个点),其他方面则不同。这就是数学和SQL中所称的交集。
我们需要确定最大可实现的保护与最高潜在财务回报相交的位置。
在这里,intersect的意思是相互结合并产生影响,就像两个事物成为一个新酷炫的东西的组成部分。这是TypeScript中该单词的含义。
类似地,您可以将union理解为将不同的事物结合在一起的行为,在宽松的意义上-这就是数学和SQL中联合的含义; 但它不仅可以意味着加入,还可以意味着与共同的利益或目的结合在一起,这对应于TypeScript中union的含义。
受不同翻译(俄语中的intersect)启发:пересекать(也是to cross)和скрещивать(也是to crossbreed)。
这样想...
交集类型(A & B)
在对象的宇宙中,只有与 A 和 B 兼容的对象才属于交集类型的领域;因此包含了 A 和 B 的所有属性(两组属性的并集)。换句话说,如果对象位于 A 和 B 的交集中,它们具备 A 和 B 的所有属性(并集)。
并集类型(A | B)
在对象的宇宙中,只有与 A 或 B 兼容的对象才属于并集类型的领域;因此包含了 A 的所有属性或 B 的所有属性,可能在 A 和 B 之间有一些或没有共同属性。换句话说,如果对象位于 A 和 B 的并集中,它们可以具备 A 的所有属性或 B 的所有属性,并且可能具有 A 和 B 的共同属性(交集)。
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
T | U
的成员是members(T) | members(U)
,而类型T & U
的成员是既属于T
又属于U
的成员,因此它们在members(T)
和members(U)
的交集中。 - Leemembers(T)
是指类型T
的值集,而不是由T
定义的成员集。 - Lee∨ := ∪ (union)
,v
表示or
,因此 union 是or
,在 TypeScript 中用|
表示。 - Magne