命名TypeScript的并集和交集类型

时间:2016-08-09 16:21:10

标签: typescript set boolean-logic

我无法理解TypeScript中术语 union types 交集类型背后的逻辑。

实际上,如果不同类型的属性是属性集,如果我将它们与&运算符组合在一起,则生成的类型将是这些集合的 union 。遵循这个逻辑,我希望像这样的类型被称为联合类型。如果我将它们与|组合在一起,我只能使用它们的公共属性,即集合的交集

Wikipedia似乎支持这种逻辑:

  

任何给定非空集S的幂集(所有子集的集合)形成布尔代数,集合的代数,具有两个运算∨:=∪(联合)和∧:=∩(交集)。

然而,根据typescriptlang.org,恰恰相反:&用于生成交集类型|用于< em>联合类型。

我确定还有另一种看待它的方式,但我无法弄明白。

7 个答案:

答案 0 :(得分:12)

这是考虑它的另一种方式。考虑四组:红色东西,蓝色东西,大事物和小东西。

如果你交叉所有红色东西和所有小东西的集合,你最终得到属性的 union - 集合中的所有内容都有红色财产和小财产。

但是如果您使用红色小东西蓝色小东西 union ,那么只有smallness属性在结果集中是通用的。 相交“红色小”与“蓝色小”产生“小”。

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

答案 1 :(得分:8)

类型A | B指的是 AB的对象。换句话说,此类型的值来自A的值的联合B的值。

类型A & B指的是 AB的对象。换句话说,此类型的值是从A的值的交叉点B的值中提取的。

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

答案 2 :(得分:5)

这里的混乱可能源于我们对集合的想象,即认为交集/联合涉及类型的成员,而不是类型本身。我整理了一张图片,希望可以阐明这个概念:

Union/Intersection diagram

答案 3 :(得分:3)

在这种情况下,您不能将类型视为对象属性集。我们可以避免关于looking at scalar variables的联合和交集类型如何工作以及它们的允许值集(而不是对象)的困惑:

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

这里的“联合”和“交集”一词在应用于允许值集时与集合论术语完全对应。

Applying the notion of permissible values (instances) to object types有点棘手(因为集合论的类比不太适合):

type A = {
  x: number
  y: number
}

type B = {
  y: number
  z: number
}

type I = A & B
type U = A | B
  • 类型为A的变量可以保存具有属性xy(没有其他属性)的对象实例。
  • 类型为B的变量可以保存具有属性yz(没有其他属性)的对象实例。
  • 在集合论中,上述两组对象实例的交集为空。但是,交叉点类型 I的变量可以保存具有A类型和B类型(即x,{ {1}}和y;因此z符号)对应于两种类型的属性的 union (因此很混乱)。
  • 在集合论中,上述两组对象实例的并集不包括具有所有三个属性的对象。但是,联合类型 &的变量可以保存具有U类型或A类型属性的对象(逻辑或,不是XOR,即{ {1}}和Bxyyzx;因此y符号),表示这两种类型的属性(在我们的示例中为z)的交点存在(因此引起混淆)。
|

答案 4 :(得分:1)

type A = {
  a: number
  b: number
}

type B = {
  b: number
  c: number
}

type C = A & B
type D = A | B

let a: A = { a: 2, b: 2 };
let b: B = { b: 2, c: 2 };

// intersection, narrow down, fewer options, like and, c have to match A and B
let c1: C = { a: 2, b: 2 }; // <- error
let c2: C = { b: 2, c: 2 }; // <- error
let c3: C = { a: 2, b: 2, c: 2 };

// union, broaden, more options, like or, d can match A or match B or match A and B
let d1: D = { a: 2, b: 2 };
let d2: D = { b: 2, c: 2 };
let d3: D = { a: 2, b: 2, c: 2 };

TypeScript操场单击here

答案 5 :(得分:0)

我也有同样的问题,无法理解如何以相反的方式看待它。阅读答案后,我想我可以从语言学角度解释这两个词,提供两个词的不同含义,并为相反的命名方法留出空间。

比较单词 intersect 的以下含义:

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

在此句子中,相交意为在一个点或一组点处相交。想一想两件事有共同点(例如一个点),而在其他方面却有所不同。这就是数学和SQL中的交集

我们需要查明可实现的最大保护量与最高潜在财务收益相交的地方。

在这里 intersect 意味着聚在一起并互相影响,就像两件事成为一件新奇事物的组成部分一样。这就是TypeScript中的 一词的含义。

以类似的方式,您可以将 union 视为将不同事物结合在一起的行为,这在广义上就是 union在数学中的含义和SQL ;但这不仅意味着 joining ,而且意味着 joining具有共同的兴趣或目的,这与TypeScript中 union 的含义相对应。

intersect 的俄语译法的启发(不要问我为什么):пересекать(也可以交叉)和скрещивать(也是杂交)。

答案 6 :(得分:0)

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