Typing cross plugin communication
jpbourgeon opened this issue · comments
Hello
In my setup, a plugin A adds a method and/or property to the base. Then a plugin B calls the method and accesses the property. It works fine.
However I have no clue of how I should type my code to let typescript know that, at execution time, plugin B will have access to the ressources provided by plugin A...
I understand that I need to "augment" the Base type with the properties that pluginA adds on top of it, but I have no clue how I should actually do that.
Could you help me type this out or suggest another pattern to avoid this problem?
function pluginA() {
const result : { property?: number, method: () => void } = {
property: "",
method: () => undefined
};
}
function pluginB(base:Base) {
base.property = 1; // the type checker throws : 'property' doesn't exist on type 'Base<Options>'.ts(2339)
base.method(); // the type checker throws : 'method' doesn't exist on type 'Base<Options>'.ts(2339)
}
// However everything works fine at runtime since the plugins have been added in the right order:
const MyBase = Base.withPlugins([pluginA, pluginB]).withDefaults({});
const instance = new MyBase();
console.log(instance.property);
instance.method();P.S. : the actual case is an event emitter plugin which props are consumed by various microservices plugins to communicate with each other.
I avoid that use case in Octokit. Instead I make plugins composable. Besides exporting the plugin functions (pluginA(), plubinB()), I also export composePluginA()/composePluginB(). The compose* functions take an instance as their first argument.
So in your case, it would look like this
import { composePluginA } from "plugin-a"
function pluginB(base:Base, options) {
composePluginA(base, options)
}For example see the composePaginateRest function exported by https://github.com/octokit/plugin-paginate-rest.js#readme
Thanks for the hint !