如何实现更简洁的TypeScript动态类方法 无需额外工厂函数
两种方案均无额外运行时代码,完全保留原有JS逻辑,同时实现动态方法的类型提示:
方案1:改造构造函数返回类型(最简便)
直接将原工厂函数的类型断言逻辑迁移到类的构造函数返回值中即可:
type logMethod = (msg: string) => void; class Logger<T extends string> { static logMethod(method: string, msg: string) { // 原有逻辑实现 } constructor(methods: T[]) { methods.forEach(method => { (this as any)[method] = (msg: string) => Logger.logMethod.call(this, method, msg); }); // 仅为类型标注,无任何运行时开销 return this as unknown as Logger<T> & Record<T, logMethod>; } // 类的原有基础方法可正常定义 baseLog(msg: string) { console.log(msg); } }
使用方式:
// 直接实例化,无需工厂函数 const logger = new Logger(['info', 'warn', 'error']); // 动态方法有完整类型提示 logger.info('info'); logger.warn('warn'); logger.error('error'); // 基础方法也可正常调用 logger.baseLog('base log');
方案2:接口合并声明
如果不想在构造函数中写类型断言,可以利用TS同名接口与类自动合并的特性实现:
type logMethod = (msg: string) => void; // 接口声明动态方法部分,会自动合并到类的实例类型中 interface Logger<T extends string> extends Record<T, logMethod> {} class Logger<T extends string> { static logMethod(method: string, msg: string) {} constructor(methods: T[]) { methods.forEach(method => { this[method] = (msg: string) => Logger.logMethod.call(this, method, msg); }); } [key: string]: any; }
使用方式和方案1完全一致。
内容的提问来源于stack exchange,提问作者user578895
相关产品推荐
相关产品推荐

