如何将联合类型转换为元组类型 [英] How to transform union type to tuple type

查看:10
本文介绍了如何将联合类型转换为元组类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

例如,我有一个类型:

type abc = 'a' | 'b' | 'c';

如何在编译时创建包含联合的所有元素的元组类型?

type t = ['a','b', 'c'];

推荐答案

很容易从元组类型转换为联合类型;例如,请参见this question。但反过来,从联合转换为元组是您不应该尝试的真正糟糕的想法之一。(参见microsoft/TypeScript#13298获取讨论和规范答案)让我们先做这件事,然后再责备自己:

// oh boy don't do this
type UnionToIntersection<U> =
  (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never
type LastOf<T> =
  UnionToIntersection<T extends any ? () => T : never> extends () => (infer R) ? R : never

// TS4.0+
type Push<T extends any[], V> = [...T, V];

// TS4.1+
type TuplifyUnion<T, L = LastOf<T>, N = [T] extends [never] ? true : false> =
  true extends N ? [] : Push<TuplifyUnion<Exclude<T, L>>, L>

type abc = 'a' | 'b' | 'c';
type t = TuplifyUnion<abc>; // ["a", "b", "c"] 

Playground link

这种方法很有效,但我真的建议不要将其用于任何官方目的或任何生产代码中。原因如下:

  • 您不能依赖联合类型的顺序。它是编译器的实现细节;因为X | Y等同于Y | X,所以编译器可以自由地将其中一个更改为另一个。有时确实是这样:

      type TypeTrue1A = TuplifyUnion<true | 1 | "a">; // [true, 1, "a"] 🙂
      type Type1ATrue = TuplifyUnion<1 | "a" | true>; // [true, 1, "a"]!! 😮
    

    所以实际上没有办法保持顺序。请不要假设输出将至少总是[true, 1, "a"]以上;这是不能保证的。这是一个实现细节,因此特定的输出可以从一个版本的类型脚本更改为下一个版本,或者从一个代码编译版本更改为下一个版本。在某些情况下确实会发生这种情况:例如,编译器缓存联合;看似无关的代码可能会影响将联合的哪个顺序放入缓存,从而产生哪个顺序。订单不仅仅是不可靠。

  • 您可能对编译器认为的联合以及它何时折叠或展开不满意。"a" | string将仅折叠为string,而boolean实际上是展开false | true

      type TypeAString = TuplifyUnion<"a" | string>; // [string]
      type TypeBoolean = TuplifyUnion<boolean>; // [false, true]
    

    因此,如果您计划保留一些现有数量的元素,则应该停止计划。没有一种通用的方法可以使元组在不丢失此信息的情况下连接到联合并返回。

  • 没有支持的方法来循环访问一般并集。我使用的伎俩都是滥用conditional types。首先,我将UNION转换为类似于()=>A | ()=>B | ()=>C函数并集,然后使用intersection inference trick将函数的并集转换为像()=>A & ()=>B & ()=>C这样的函数的交集,该交集被解释为单个函数类型,且使用条件类型提取返回值仅获取最后一个重载。所有这些疯狂的行为最终导致了A | B | C,并只取出了一个成分,可能是C。然后,您必须将其推到您正在构建的元组的末尾。

  • 既然TypeScrip 4.1引入了recursive conditional types,原因就不多了,但是递归条件类型对编译器的负担比您想要的要大得多,而且递归限制很浅。因此,如果您有超过20个元素的联合,或者其类型本身以某种方式递归的联合,您可能会看到一些性能或编译问题。

这就对了。你可以这样做,但不要这么做。(如果你做了做了,如果有什么东西爆炸了,不要怪我。💣)希望这能有所帮助。祝你好运!

这篇关于如何将联合类型转换为元组类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆