'How to infer type from an tuple of Constructor and its Parameters

I define a Manager to manage a set of modules, and I have two needs and I can implement these two separately. How to implement both?

  1. I want to access the method of the Module instance through the Manager instance.
interface Module {
  print(): void;  
}

interface ModuleConstructor<T extends string> {
  new(...args: any[]): Module;
  moduleName: T;
};

class Manager<
  T extends ModuleConstructor<string>[],
  A = T extends ModuleConstructor<infer N>[] ? {
    [K in N]: InstanceType<Extract<T[number],  { moduleName: K }>>;
  } : never
> {
  api!: A;

  constructor(modules: T) {
    // check duplicated moduleName in runtime
  }
}

class AMoudle {
  static readonly moduleName = 'a'
  print() {}
  aFun() {}
}

const manager = new Manager([AMoudle]);

manager.api.a.aFun()
manager.api.a.bFun() // error

playground

  1. I want to use a tuple as constructor parameter but the Options of the Constructor is not inferred correctly.
export interface Module<O extends {}> {
  options?: O;
  activate?: () => void;
  deactivate?: () => void;
}

interface ModuleConstructor<O> {
  new(...args: any[]): Module<O>
}

class Manager<O extends {}[]> {
  constructor(descriptors: [...{ [I in keyof O]: [ModuleConstructor<O[I]>, O[I] & {}] }]) { }
}



class AModule implements Module<{ a: number }> {
  constructor(public options: { a: number }) { }
}

const manager = new Manager([
  [AModule, { a: '1' }], // error
]);

playground



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source