Dynamically load classes
Use case: extend functionality by just adding a new file into a folder.
Interface
To be type safe it's recommended to implement an interface:
export interface MyInterface {
some_function: (input: MyType) => void;
another_function: (input: MyType2) => string;
}
Classes to be imported
// myClass.ts
export default class MyClass implements MyInterface {
async some_function(input: MyType) {
// ...
}
another_function(input: MyType2) {
// ...
}
}
Loader
import logger from "./Logger";
import * as fs from "fs";
import * as path from "path";
import { MyInterface } from "./MyInterface";
const MODULE_DIR_NAME = "modules";
const MODULE_DIR = path.join(__dirname, "..", MODULE_DIR_NAME);
export class MyLoader {
public static async loadModules(): Promise<MyInterface[]> {
logger.info(`MyLoader | Loading Classes`);
const classes: MyInterface[] = [];
const files = fs.readdirSync(MODULE_DIR);
for (const file of files) {
const moduleName = file.split(".")[0];
logger.info(`MyLoader | Loading class <${file}>`);
const Module = await import(`${MODULE_DIR}/${moduleName}`);
try {
const instanceOfModule = new Module.default();
if (
"some_function" in instanceOfModule &&
"another_function" in instanceOfModule
) {
logger.info(`MyLoader | Successfully loaded <${file}>`);
classes.push(new Module.default());
} else {
logger.error(
`MyLoader | Class <${file}> does not implement interface <MyInterface>. Ignoring class.`
);
}
} catch (error) {
logger.error(`MyLoader | Failed to load <${file}>`, { error });
}
}
return classes;
}
}
Last updated