有个 EventEmitter 类,其 installTo 核心部分摘要如下,主要作用是在目标对象中添加 'on', 'off', 'emit', 'fire', 'once' 方法。
class EventEmitter {
static installTo(obj: object): void {
const eventEmitter = new EventEmitter();
const methods = ['on', 'off', 'emit', 'fire', 'once'];
methods.forEach((method) => {
Object.defineProperty(obj, method, {
value: (eventEmitter as { [key: string]: any })[method],
enumerable: false,
writable: false,
configurable: false,
});
});
}
}
现有一个 LRU 类,其构造函数中 通过 EventEmitter.installTo(this) 将 EventEmitter 的方法添加到 LRU 实例中,部分代码如下:
class LRU {
constructor(options?: number | LRUOptions) {
EventEmitter.installTo(this); // 当然这里是可以做成一个装饰器的,但与此问题无关。
}
}
此时 ts 中以下代码将会报错
const lru = new LRU(10)
lr.on('xxx') // 提示:Property 'on' does not exist on type 'LRU'
我该如何处理让 LRU 的示例上能正确识别出 on 方法?
首先我知道的几个方案:
- 继承, 直接让LRU 继承 EventEmitter 即可,这样能识别。但是我不想这样做,两者并无实际关系,继承不太合适。
- 在 LRU 类里面直接写
on = EventEmitter.prototype.on;
等类似的代码,这样实际是额外再给LRU的实例上加了这些方法的引用。但这样,1是和EventEmitter.installTo有重复(内部还有其他细节处理逻辑)2是代码有耦合。
请问有什么办法能处理这个问题吗? 初使用typescript,可能对此不熟悉,如有好的方案请指出。
感谢乔治的答案。
最终解决方案,如下:
// 从EventEmitter 中获取需要的方法
type EventEmitterMethods = Pick<EventEmitter, 'on' | 'off' | 'emit' | 'once' |'fire'>;
// LRU 实现省略
class LRU {}
// 声明合并
interface LRU extends EventEmitterMethods {}