打字稿:对象键的联合和交集“反转”

Ste*_*ems 8 typescript

根据我对集合论的了解,当您取两个集合的并集时,您会覆盖两个集合并取结果集。当你取两个集合的交集时,你将两个集合重叠并取彼此重叠的部分。

对于数字,这很好用:

type SomeUnion = (1 | 2 | 3) | (2 | 3 | 4)
const someUnion: SomeUnion // typeof someUnion is 1 | 2 | 3 | 4

type SomeIntersect = (1 | 2 | 3) & (2 | 3 | 4) 
const someIntersect: SomeIntersect // typeof someIntersect is 2 | 3
Run Code Online (Sandbox Code Playgroud)

对于对象键,在我看来,交集和联合操作的工作非常不直观。

type ObjUnion = { one: string, two: string } | { two: string, three: string }
const objUnionKeys: keyof ObjUnion // typeof objUnionKeys is 'two' while I would expect it to be all keys -> 'one' | 'two' | 'three'

type ObjIntersection = { one: string, two: string } & { two: string, three: string }
const objIntersectionKeys: keyof ObjIntersection // typeof objIntersectionKeys is 'one' | 'two' | 'three' while I would expect it only to be the keys in common -> 'one'
Run Code Online (Sandbox Code Playgroud)

我想它为什么像这样工作有充分的理由。有人可以填写我吗?

Aro*_*ron 6

你是对的,对象联合和交集的行为似乎与文字的行为完全相反,但它实际上完全有道理:) 让我们深入研究为什么!

如果您有字符串或数字文字的联合类型 à la

type SomeUnion = 1 | 2 | 3 | 2 | 3 | 4
Run Code Online (Sandbox Code Playgroud)

你说的是这SomeUnion可能是这些数字中的任何一个。

当你有

type SomeIntersect = (1 | 2 | 3) & (2 | 3 | 4)
Run Code Online (Sandbox Code Playgroud)

你所说的是SomeIntersect 必须满足两个群体的约束。在这种情况下,唯一满足两者的数字是 2 和 3,因此上面的等价于type SomeIntersect = 2 | 3


尽管对象的联合和交集的语义是不同的。

当你有

type ObjUnion = { one: string, two: string } | { two: string, three: string }
Run Code Online (Sandbox Code Playgroud)

你说的是它ObjUnion可以有任何一种形状——这意味着你确定的唯一领域存在于ObjUnion"two". 其他的可能存在也可能不存在,这取决于它实际上是两种形状中的哪一种。但是您确实可以确定{ two: string }对象上存在。


到那个时刻

type ObjIntersection = { one: string, two: string } & { two: string, three: string }
Run Code Online (Sandbox Code Playgroud)

你说的是 ObjIntersection 有两个对象类型的所有3场,否则将不符合交叉口的约束。

这意味着,如果您有一个类型的对象,ObjIntersection您就知道它具有所有 3 个字段,因此 TypeScript 可以让您毫无问题地访问其中的任何一个!