Typescript:对象键的联合和交集“反转”

14

据我所知,集合论中取两个集合的并是将这两个集合放在一起形成一个新的集合。取两个集合的交是将它们重叠部分取出来。

对于数字,这个方法也同样适用:

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

对于对象键,我认为交集和并集操作的工作方式相当不直观。

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'

我想象这样做的原因一定是有根据的。有人能给我解释一下吗?

1个回答

12

你说得没错,对象的联合和交集行为表现出看似与字面量完全相反的方式,但实际上这是有道理的 :) 让我们深入了解一下吧!

如果你有一个字符串或数字字面量的联合类型 à la

type SomeUnion = 1 | 2 | 3 | 2 | 3 | 4

你的意思是SomeUnion可以是这些数字中的任何一个。

当你拥有

type SomeIntersect = (1 | 2 | 3) & (2 | 3 | 4)

你的意思是SomeIntersect必须同时满足两个组的限制条件。在这种情况下,满足两个组条件的唯一数字是2和3,因此上述内容等同于type SomeIntersect = 2 | 3


不过,对于对象来说,联合类型和交叉类型的语义是不同的。

当你有

type ObjUnion = { one: string, two: string } | { two: string, three: string }
你的意思是,ObjUnion 可以有两种不同的形状,也就是说你只确定 ObjUnion 中存在一个名为 "two" 的字段,其他字段的存在与否取决于它属于哪种形状。但你可以肯定的是这个对象中存在 { two: string } 这个字段。


谈到

type ObjIntersection = { one: string, two: string } & { two: string, three: string }

你所说的是,ObjIntersection必须在两种对象类型中都具有这3个字段,否则它将不满足交集的限制条件。

这意味着,如果你有一个ObjIntersection类型的对象,你会知道它拥有所有3个字段,因此TypeScript可以让你轻松地访问它们中的任何一个!


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