Typescript 循环类型交集
Typescript recurrent type intersection
我试图为循环交集定义一个类型定义,以实现这种行为:
type merged = Merged<[{a: string}, {b: string}, ...]>
成为{a: string} & {b: string} & ...
我定义了一些类型实用程序,如 Head
和 Tail
以能够对可变数量的输入类型进行操作,并设法定义循环联合,但未能实现相同的交集: (
type Head<T extends any[]> = T[0]
type Tail<T extends any[]> =
((...args: T) => any) extends ((_arg0: any, ...rest: infer R) => any) ? R : never
type United<T extends any[]> = {
0: Head<T>
1: United<Tail<T>>
}[ T extends ([] | [any])
? 0
: 0 | 1
]
type Merged<T extends any[]> = {
0: Head<T>
1: Merged<Tail<T>>
}[T extends ([] | [any])
? 0
: 0 & 1
]
type a = {a: string}
type b = {b: string}
type c = {c: string}
type head = Head<[a, b, c, d]> // {a: string} OK
type tail = Tail<[a, b, c, d]> // [b, c] OK
type united = United<[a, b, c, d]> // a | b | c OK
type merged = Merged<[a, b, c, d]> // unknown Not good
我一定是在 TypeScript 的一些基本内部结构上失败了,但不知道为什么它在联合的情况下有效而在交集的情况下无效?
我该如何解决?
我不会在这里尝试做任何递归的事情,尤其是因为那种递归索引是 not supported。
此外,键类型的交集几乎总是会折叠成类似 never
的东西,因此会得到 never
或 unknown
或一些不受欢迎的东西。也就是说,索引访问不一定分布在交叉点上:
type OOPS = { a: a, b: b }["a" & "b"] // never! not a & b
相反,我会使用 提供的解决方案来获取并集并将其转换为交集:
type Merged<A extends readonly any[]> =
A[number] extends infer U ?
(U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ?
I : never : never;
type a = { a: string }
type b = { b: string }
type c = { c: string }
type d = { d: string }
type merged = Merged<[a, b, c, d]> // a & b & c & d
这应该适合你。希望能帮助到你;祝你好运!
我试图为循环交集定义一个类型定义,以实现这种行为:
type merged = Merged<[{a: string}, {b: string}, ...]>
成为{a: string} & {b: string} & ...
我定义了一些类型实用程序,如 Head
和 Tail
以能够对可变数量的输入类型进行操作,并设法定义循环联合,但未能实现相同的交集: (
type Head<T extends any[]> = T[0]
type Tail<T extends any[]> =
((...args: T) => any) extends ((_arg0: any, ...rest: infer R) => any) ? R : never
type United<T extends any[]> = {
0: Head<T>
1: United<Tail<T>>
}[ T extends ([] | [any])
? 0
: 0 | 1
]
type Merged<T extends any[]> = {
0: Head<T>
1: Merged<Tail<T>>
}[T extends ([] | [any])
? 0
: 0 & 1
]
type a = {a: string}
type b = {b: string}
type c = {c: string}
type head = Head<[a, b, c, d]> // {a: string} OK
type tail = Tail<[a, b, c, d]> // [b, c] OK
type united = United<[a, b, c, d]> // a | b | c OK
type merged = Merged<[a, b, c, d]> // unknown Not good
我一定是在 TypeScript 的一些基本内部结构上失败了,但不知道为什么它在联合的情况下有效而在交集的情况下无效?
我该如何解决?
我不会在这里尝试做任何递归的事情,尤其是因为那种递归索引是 not supported。
此外,键类型的交集几乎总是会折叠成类似 never
的东西,因此会得到 never
或 unknown
或一些不受欢迎的东西。也就是说,索引访问不一定分布在交叉点上:
type OOPS = { a: a, b: b }["a" & "b"] // never! not a & b
相反,我会使用
type Merged<A extends readonly any[]> =
A[number] extends infer U ?
(U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ?
I : never : never;
type a = { a: string }
type b = { b: string }
type c = { c: string }
type d = { d: string }
type merged = Merged<[a, b, c, d]> // a & b & c & d
这应该适合你。希望能帮助到你;祝你好运!