I'm converting a large project from flow to TS and am having trouble figuring out how to create dynamic class methods. I threw together a simple working example of what I'm trying to do:
declare type logMethod = (msg: string) => void;
class Logger {
constructor(methods: string[]) {
methods.forEach(method => this[method] = (msg: string) => Logger.logMethod.call(this, method, msg))
}
static logMethod(method: string, msg: string) {}
[key: string]: any;
}
function LoggerFactory<T extends string>(methods: T[]): Logger & Record<T, logMethod> {
const logger = new Logger(methods);
return logger as Logger & Record<T, logMethod>;
}
const logger = LoggerFactory(['info', 'warn', 'error']);
logger.info('info');
logger.warn('warn');
logger.error('error');
this works just fine, as in info, warn, error, or any other method names I pass into the factory are typed properly. However I hate having extra JS just to make the type system happy. The LoggerFactory is completely unnecessary in JS and I'm trying to figure out how to get rid of it.
I was trying to go down a road like this:
class Logger<T extends string[]> {
[method in keyof T]: logMethod;
}
but that mapping syntax doesn't work on classes or interfaces, only normal types. Just looking for ideas here!