awesome-typescript
awesome-typescript copied to clipboard
「重学TS 2.0 」TS 练习题第四十九题
实现 UnionToArray
工具类型,用于将联合类型转换成元组类型。具体的使用示例如下所示:
type UnionToArray<U> = // 你的实现代码
type A0 = UnionToArray<'aaa' | 'bbb' | 'ccc'> //=> ['aaa' , 'bbb' , 'ccc']
type A1 = UnionToArray<1 | 2 | 3 > //=> [1, 2, 3]
type A2 = UnionToArray<{type:'input'} | {type:'select',hasOptions:boolean}> //=> [{type:'input'} ,{type:'select',hasOptions:boolean}]
type UnionToIntersection<U> = (U extends any ? (arg: U) => any : never) extends (arg: infer I) => void ? I : never;
type UnionToTuple<T> = UnionToIntersection<T extends any ? (t: T) => T : never> extends (_: any) => infer W
? [...UnionToTuple<Exclude<T, W>>, W]
: [];
//疑问 非答案 type A5<T> = T extends T ? T : never type A51 = A5<1 | 2 | 3>;//type A51 = 2 | 1 | 3 type A6<T> = T extends T ? [T] : never type A61 = A6<1 | 2 | 3>; //type A61 = [1] | [2] | [3] //采用上面解法的时候 为什么数字会乱序,字符串则不会 type A1 = UnionToArray<1 | 2 | 3 > //=> [1, 2, 3] //预期 type A1 = UnionToArray<1 | 2 | 3 >//=>[2,1,3] //实际显示 // 🤔🤔🤔🤔🤔🤔🤔
//后面在同事的电脑上 打印同样的A51和A61 //结果没有乱序 //可能原因 vscode插件的影响 //忽略上面的提问
做不到,因为联合类型是无序的,而元组是有序的。
这个不太满足要求:
type UnionToArray<U,T extends U=U> = [U] extends [never]
?[]
:U extends U?[U,...UnionToArray<Exclude<T,U>>]:[]
type A0 = UnionToArray<'a' | 'b' | 'c'>
//=>type A0 = ["a", "b", "c"] | ["a", "c", "b"] | ["b", "a", "c"] | ["b", "c", "a"] | ["c", "a", "b"] | ["c", "b", "a"]
这个基本满足要求:
class BHAAL { private isBhaal = true; }
type UnionToTuple<T> = (
(
(
T extends any
? (t: T) => T
: never
) extends infer U
? (U extends any
? (u: U) => any
: never
) extends (v: infer V) => any
? V
: never
: never
) extends (_: any) => infer W
? [...UnionToTuple<Exclude<T, W>>, W]
: []
);
type Tuple = UnionToTuple<2 | 1 | 3 | 5 | 10 | -9 | 100 | 1001 | 102 | 123456 | 100000000 | "alice" | [[[BHAAL]]] | "charlie">;
// ^? = [2, 1, 3, 5, 10, -9, 100, 1001, 102, 123456, 100000000, "alice", [[[BHAAL]]], "charlie"]
更多信息看这里https://github.com/Microsoft/TypeScript/issues/13298
type UnionToArray<U> = (U extends any ? (arg: [U]) => any : never) extends (
...arg: infer R
) => any
? R extends [arg: [infer O]]
? [...UnionToArray<Exclude<U, O>>, O]
: []
: never;
type A0 = UnionToArray<"aaa" | "bbb" | "ccc">; //=> ['aaa' , 'bbb' , 'ccc']
type A1 = UnionToArray<1 | 2 | 3>; //=> [1, 2, 3]
type A2 = UnionToArray<
{ type: "input" } | { type: "select"; hasOptions: boolean }
>; //=> [{type:'input'} ,{type:'select',hasOptions:boolean}]