Skip to content

Instantly share code, notes, and snippets.

@danielbodart
Last active October 12, 2023 06:36
Show Gist options
  • Select an option

  • Save danielbodart/bbd10ee191c6349f8fd07fb4a5acd092 to your computer and use it in GitHub Desktop.

Select an option

Save danielbodart/bbd10ee191c6349f8fd07fb4a5acd092 to your computer and use it in GitHub Desktop.
Typesafe mixin using ECMAScript 2015 mixin class and class expressions
interface Constructor<T = object> {
new(...args: any[]): T;
}
interface Disposable {
dispose(): void;
}
function Disposable<T extends Constructor>(Base: T): T & Constructor<Disposable> {
return class extends Base implements Disposable {
dispose() {
console.log('Disposed');
}
};
}
interface Activatable {
activate(): void;
}
function Activatable<T extends Constructor>(Base: T): T & Constructor<Activatable> {
return class extends Base implements Activatable {
activate() {
console.log('Activated');
}
};
}
function isActivatable(instance: any): instance is Activatable {
return instance && typeof instance === 'object' && 'activate' in instance;
}
class Base {
constructor(public name: string) {
}
baseMethod() {
console.log('baseMethod', this.name);
}
}
class DisposableActivatable extends Disposable(Activatable(Base)) {
constructor(name: string) {
super(name);
}
}
const instance = new DisposableActivatable('instance1');
instance.dispose();
instance.activate();
instance.baseMethod();
console.log(instance instanceof DisposableActivatable);
console.log(isActivatable(instance)); // Have to use typeguard as class expressions are anonymous
console.log(instance instanceof Base);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment