问题 #
实现类型版本的 UnionToTuple 把 Union 转换为 Tuple。
正如我们所知,并集是一种无序结构,但元组是一种有序结构,这意味着我们不应该预先假定在创建或转换并集时,在一个并集的术语之间会保留任何顺序。
因此,在这个挑战中,输出元组中元素的任何排列都是可以接受的。
您的类型应该解析为以下两种类型之一,但不是它们的联合体!
UnionToTuple<1> // [1], and correct
UnionToTuple<'any' | 'a'> // ['any','a'], and correct或者
UnionToTuple<'any' | 'a'> // ['a','any'], and correct它不应该是所有可接受的元组的联合…
UnionToTuple<'any' | 'a'> // ['a','any'] | ['any','a'], which is incorrecttype ExtractValuesOfTuple<T extends any[]> = T[keyof T & number];
type case1 = UnionToTuple<'a' | 'b'>['length'], 2
type case2 = ExtractValuesOfTuple<UnionToTuple<'a' | 'b'>> // 'a' | 'b'
type case3 = ExtractValuesOfTuple<UnionToTuple<'a'>> // 'a'
type case4 = ExtractValuesOfTuple<UnionToTuple<any>> // any
type case5 = ExtractValuesOfTuple<UnionToTuple<undefined | void | 1>> // void | 1
type case6 = ExtractValuesOfTuple<UnionToTuple<any | 1>> // any | 1
type case7 = ExtractValuesOfTuple<UnionToTuple<any | 1>> // any
type case8 = ExtractValuesOfTuple<UnionToTuple<'d' | 'f' | 1 | never>> // 'f' | 'd' | 1
type case9 = ExtractValuesOfTuple<UnionToTuple<[{ a: 1 }] | 1>> // [{ a: 1 }] | 1
type case10 = ExtractValuesOfTuple<UnionToTuple<never>> // never
type case11 = ExtractValuesOfTuple<UnionToTuple<'a' | 'b' | 'c' | 1 | 2 | 'd' | 'e' | 'f' | 'g'>> // 'f' | 'e' | 1 | 2 | 'g' | 'c' | 'd' | 'a' | 'b'解答 #
type UnionToIntersection<U> = (U extends unknown ? (_: U) => 0 : never) extends (_: infer R) => 0 ? R : never;
type LastOfUnion<U> = UnionToIntersection<U extends unknown ? (_: U) => 0 : never> extends (_: infer R) => 0 ? R : never;
type UnionToTuple<T, Last = LastOfUnion<T>> = [T] extends [never] ? [] : [...UnionToTuple<Exclude<T, Last>>, Last]拆分 #
- 首先需要把
Union转换为Intersection(交叉类型&),即把Union转换为Intersection - 然后需要取出
Intersection中的最后一个元素 - 并递归处理
- 从联合类型
T中提取出联合类型的最后一个元素Last - 如果
T是never,则返回空数组 - 如果
T不是never,则返回一个数组由递归处理结果和Last组成 - 递归处理的时候需要排除
Last