将TypeScript联合类型分解为特定类型

时间:2018-10-22 13:54:19

标签: typescript generics union-types

我想知道是否可以将联合类型“拆分”为TypeScript中的特定子类型。这是我尝试使用的代码,很明显,我正在通过代码片段实现以下目的:

type SplitType<T> =
T extends (infer A)|(infer B)
? Something<A, B>
: T;

在此示例中,Something<A, B>可以是[A, B]或完全不同的类型。这将意味着SplitType<string>只会输出string,而SplitType<number|string>则意味着[number, string]

在TypeScript中是否有可能做到这一点?如果不是这样,将来是否有一项功能可以允许这样做(例如variadic types)?

1 个答案:

答案 0 :(得分:3)

对于固定数目的工会成员最大数目,我们可以通过生成呼叫签名的交集,然后将其与具有多个呼叫签名的类型进行匹配,以单一实现定义的顺序提取工会成员。此版本仅在启用strictFunctionTypes的情况下起作用。

// https://stackoverflow.com/a/50375286
type UnionToIntersection<U> = 
  (U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never

type UnionToFunctions<U> =
    U extends unknown ? (k: U) => void : never;

type IntersectionOfFunctionsToType<F> =
    F extends { (a: infer A): void; (b: infer B): void; (c: infer C): void; } ? [A, B, C] :
    F extends { (a: infer A): void; (b: infer B): void; } ? [A, B] :
    F extends { (a: infer A): void } ? [A] :
    never;

type SplitType<T> =
    IntersectionOfFunctionsToType<UnionToIntersection<UnionToFunctions<T>>>;

type Test1 = SplitType<number>;                    // [number]
type Test2 = SplitType<number | string>;           // [string, number]
type Test3 = SplitType<number | string | symbol>;  // [string, number, symbol]