代码之家  ›  专栏  ›  技术社区  ›  richbai90

动态组合函数中的类型

  •  0
  • richbai90  · 技术社区  · 6 年前

    n ModelOf<T, A> 并返回类型 ModelOf<T_n1 & T_n2 &T_n3..., A_n1 | A_n2 | A_n3...> T_n A_n 是传递到函数中的模型的泛型参数。这是我到目前为止的情况。

    export interface ModelOf<T, A extends string> {
      initial: Record.Factory<T>;
      actions: (
        update$: Subject<
          (state: Record<T> & Readonly<T>) => Record<T> & Readonly<T>
        >
      ) => {
        [p in A]: (...P: any) => void;
      };
    }
    
    const modelA : ModelOf<ShapeOfModelA, ActionsOfModelA> = ...
    const modelB : ModelOf<ShapeOfModelB, ActionsOfModelB> = ...
    
    const combineModels = (...models : ModelOf<any, any>) : ModelOf<any, any> => {...}
    const model = combineModels(modelA, modelB); // ModelOf<any, any> is not what I want
    

    any

    0 回复  |  直到 6 年前
        1
  •  2
  •   ford04    6 年前

    你可以写 combineModels 函数类型如下:

    declare function combineModels<T extends ModelOf<any, any>[]>(
      ...models: T
    ): T extends ModelOf<infer I, infer U>[]
      ? ModelOf<UnionToIntersection<I>, U>
      : never;
    
    type UnionToIntersection<T> = (T extends any
      ? (arg: T) => void
      : never) extends (arg: infer I) => void
      ? I
      : never;
    

    generic rest parameters 的元组类型 models 函数参数。的所有实例化 T A ModelOf<T, A extends string> 是吗 conditionally inferred 作为联合类型 I U T s) 到交叉点类型。

    interface ModelOf<T, A extends string> {}
    declare const modelA: ModelOf<{ a: number }, "fooAction">;
    declare const modelB: ModelOf<{ b: string }, "barAction">;
    
    const model = combineModels(modelA, modelB); 
    // ModelOf<{a: number} & {b: string}, "fooAction" | "barAction">
    

    Playground

    希望,这有帮助!

    你也可以用 lookup type 相反(也许更简单一点):

    declare function combineModels<T extends ModelOf<any, any>[]>(
      ...models: T
    ): ModelOf<UnionToIntersection<T[number]["t"]>, T[number]["a"]>
    

    Playground