awesome-typescript icon indicating copy to clipboard operation
awesome-typescript copied to clipboard

「重学TS 2.0 」TS 练习题第四十九题

Open heweijian4933 opened this issue 2 years ago • 4 comments

实现 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}]

heweijian4933 avatar Jun 04 '22 02:06 heweijian4933

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]
    : [];

SuperSaiyr avatar Jun 06 '22 14:06 SuperSaiyr

//疑问 非答案 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插件的影响 //忽略上面的提问

lq-math-dog avatar Aug 09 '22 09:08 lq-math-dog

做不到,因为联合类型是无序的,而元组是有序的。

这个不太满足要求:

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

SongJuXin avatar Oct 06 '22 12:10 SongJuXin

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}]

zhengyimeng avatar Nov 14 '22 09:11 zhengyimeng