// union to intersection converter by @jcalz
// Intersect<{ a: 1 } | { b: 2 }> = { a: 1 } & { b: 2 }
type Intersect<T> = (T extends any ? ((x: T) => 0) : never) extends ((x: infer R) => 0) ? R : never
// get keys of tuple
// TupleKeys<[string, string, string]> = 0 | 1 | 2
type TupleKeys<T extends any[]> = Exclude<keyof T, keyof []>
// apply { foo: ... } to every type in tuple
// Foo<[1, 2]> = { 0: { foo: 1 }, 1: { foo: 2 } }
type Foo<T extends any[]> = {
[K in TupleKeys<T>]: {foo: T[K]}
}
// get union of field types of an object (another answer by @jcalz again, I guess)
// Values<{ a: string, b: number }> = string | number
type Values<T> = T[keyof T]
// TS won't believe the result will always have a field "foo"
// so we have to check for it with a conditional first
type Unfoo<T> = T extends { foo: any } ? T["foo"] : never
// combine three helpers to get an intersection of all the item types
type IntersectItems<T extends any[]> = Unfoo<Intersect<Values<Foo<T>>>>
type Test = [
{ a: 1 } | { b: 2 },
{ c: 3 },
]
// this is what we wanted
type X = IntersectItems<Test> // { a: 1, c: 3 } | { b: 2, c: 3 }
// this is not what we wanted
type Y = Intersect<Test[number]> // { a: 1, b: 2, c: 3 }
4条答案
按热度按时间ecr0jaav1#
你想从并集到交集吗?分布条件类型和条件类型的推理可以做到这一点。(对不起,不要认为有可能从交集到并集)下面是邪恶的魔法:
这样就可以将并集
U
重新打包成一个新的并集,其中所有的元素都处于逆变位置。这样就可以将类型推断为交集I
,如手册中所述:类似地,在反变位置中的相同类型变量的多个候选导致交集类型被推断。
让我们看看它是否有效。
首先,让我将您的
FunctionUnion
和FunctionIntersection
括起来,因为TypeScript似乎比函数return更紧密地绑定并集/交集:测试:
看起来不错!
请注意,通常
UnionToIntersection<>
会公开TypeScript认为是实际联合的一些细节。变成了
在TS3.6+中,它被急切地简化为
因为不可能有
string
* 和number
* 和true
* 和false
的值。希望对你有帮助,祝你好运!
jmo0nnb32#
还有一个非常相关的问题,当你想要一个几种类型的交集,但不一定要把联合转换成交集时。如果不求助于临时联合,就没有办法直接得到交集!
问题是我们想要得到交集的类型可能在内部有联合,这也将被转换为交集。
给定示例中的执行如下所示
希望这也能展示一些其他有用的技术。
7jmck4yq3#
我稍微扩展了@jcalz的答案,以绕过他所描述的布尔问题。
这基本上防止了它将幕后的
true | false
转换为true & false
,从而保留了它的boolean
性质。现在,它将正确地说
UnionToIntersection<boolean>
是boolean
,而不是never
,同时仍然正确地说UnionToIntersection<boolean | string>
是never
6l7fqoea4#
你可以使用
UnionToIntersection
从一个辉煌的图书馆utility-types.(1.5M每周下载在2022/11)或者来自另一个gem库type-fest的类似类型
UnionToIntersection
(2022/11年每周下载1.17亿次)。使用方法如下: