Typescript - Get all implementations of interface

前端 未结 1 1956
粉色の甜心
粉色の甜心 2021-02-01 23:22

I\'m searching for a way to get a list of all classes implementing a certain interface in Typescript.

In .Net for example, you can do this using reflection but i cant fi

相关标签:
1条回答
  • 2021-02-02 00:01

    As I mentioned in the comments, it's a stated non-goal of TypeScript (see non-goal #5) to emit JavaScript that is dependent on the type system, so there will be nothing at runtime you can use automatically to do what you want.

    You can, of course, use TypeScript to help you maintain a registry of types that can be used almost exactly how you want. I'd suggest using class decorators, like so:

    interface IControlPanel {
      // add some methods or something to distinguish from {}
      doAThing(): void;
    }
    
    // add a registry of the type you expect
    namespace IControlPanel {
      type Constructor<T> = {
        new(...args: any[]): T;
        readonly prototype: T;
      }
      const implementations: Constructor<IControlPanel>[] = [];
      export function GetImplementations(): Constructor<IControlPanel>[] {
        return implementations;
      }
      export function register<T extends Constructor<IControlPanel>>(ctor: T) {
        implementations.push(ctor);
        return ctor;
      }
    }
    

    Now, instead of declaring that the class implements IControlPanel, you use @IControlPanel.register:

    @IControlPanel.register
    class BasicControlPanel {
      doAThing() { }
    }
    
    @IControlPanel.register
    class AdvancedControlPanel {
      doAThing() { }
    }
    

    If you try to register a class that does not implement IControlPanel, you will get an error:

    // error, doAThing is missing from BadControlPanel
    @IControlPanel.register
    class BadControlPanel {
      doNothing() { }
    }
    

    Now you can use the registry the way you want, mostly:

    window.onload = () => {
      var controlPanels = IControlPanel.GetImplementations();
      for (var x = 0; x < controlPanels.length; x++) {
        document.write(controlPanels[x].name + ", ");
        const panel = new controlPanels[x]();
        panel.doAThing();
      }
    };
    

    I say "mostly" because I've stored constructors, not strings, since you wanted a way to instantiate them. You can get the name property of the constructor for the string. And you can instantiate the classes, assuming they all take the same constructor argument types.

    Hope that helps; good luck!

    Stackblitz example

    0 讨论(0)
提交回复
热议问题