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

m93*_*93a 1 generics typescript union-types

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

type SplitType<T> =
T extends (infer A)|(infer B)
? Something<A, B>
: T;
Run Code Online (Sandbox Code Playgroud)

在这个例子中Something<A, B>可以是[A, B],或者是一个完全不同的类型。这意味着SplitType<string>只会输出 a string,但SplitType<number|string>意味着[number, string].

在 TypeScript 中可能有这样的事情吗?如果没有,将来是否有允许这样做的功能(例如可变参数类型)?

小智 10

根据Matt McCutchen 的回答,以及recursive conditional typesv4.1 之后的版本:

type UnionToParm<U> = U extends any ? (k: U) => void : never;
type UnionToSect<U> = UnionToParm<U> extends ((k: infer I) => void) ? I : never;
type ExtractParm<F> = F extends { (a: infer A): void } ? A : never;

type SpliceOne<Union> = Exclude<Union, ExtractOne<Union>>;
type ExtractOne<Union> = ExtractParm<UnionToSect<UnionToParm<Union>>>;

type ToTuple<Union> = ToTupleRec<Union, []>;
type ToTupleRec<Union, Rslt extends any[]> = 
    SpliceOne<Union> extends never ? [ExtractOne<Union>, ...Rslt]
    : ToTupleRec<SpliceOne<Union>, [ExtractOne<Union>, ...Rslt]>
;

type test = ToTuple<5 | 6 | "l">;
Run Code Online (Sandbox Code Playgroud)


Mat*_*hen 6

对于固定的最大联合成员数量,我们可以通过生成调用签名的交集,然后将其与具有多个调用签名的类型进行匹配,以单个实现定义的顺序提取联合成员。此版本仅适用于strictFunctionTypes启用。

// /sf/answers/3526270051/
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]
Run Code Online (Sandbox Code Playgroud)