Skip to content

Instantly share code, notes, and snippets.

@aztack
Created November 1, 2021 06:57
Show Gist options
  • Save aztack/2ff06894fe061ecd851200901bc1f5ae to your computer and use it in GitHub Desktop.
Save aztack/2ff06894fe061ecd851200901bc1f5ae to your computer and use it in GitHub Desktop.
delegate.ts
class EventEmitter {
on(event: string, callback: () => void) {
console.log(`EventEmitter#on`, this.constructor.name);
}
emit(event: string) {
console.log(`EventEmitter#emit`, this.constructor.name);
}
}
class Win {
x:number = 41;
y:number = 42;
moveTo(x:number,y:number) {
console.log(`Win#moveTo ${this.x}, ${this.y}`, this.constructor.name);
}
showDevTools() {
console.log(`Win#showDevTools`, this.constructor.name);
}
closeDevTools() {
console.log(`Win#closeDevTools`, this.constructor.name);
}
close() {
console.log(`Win#close`, this.constructor.name);
};
}
class NwWindow {
private win: Win = new Win();
openDevTools() {
console.log(`Win#openDevTools`, this.constructor.name);
return this.win.showDevTools();
}
}
// here is the key that make ts understand the inheritance and make code suggestion work as expected
interface NwWindow extends Omit<Win, 'showDevTools'>, EventEmitter {}
// delegate() make prototype chain work as expected in runtime
delegate<NwWindow>(NwWindow, [Win, EventEmitter], 'win');
function delegate<T extends {[key: string]: any}>(derivedCtor: any, constructors: any[], propName: string) {
constructors.forEach((inherited) => {
Object.getOwnPropertyNames(inherited.prototype).forEach((name) => {
const desc = Object.getOwnPropertyDescriptor(inherited.prototype, name);
if (desc && name !== 'constructor') {
console.log(`Delegating ${name}`);
const original = desc.value as Function;
desc.value = function (...args: any) {
const ptr = this as T;
const prop = ptr[propName];
return original.apply(prop, args);
};
Object.defineProperty(derivedCtor.prototype, name, desc);
}
});
});
}
const w = new NwWindow();
console.log(w);
w.openDevTools();
w.closeDevTools();
w.on('a', console.log);
console.log(w);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment