TypeScript:Mixins
lastmod 2022-06-09created 2022-04-1212 edits
Take a constructor
Mixins take a class and extend it with new functionality. So we need to define what is a constructor. Easy as:
Knowledge
- TypeScript (and JavaScript) classes support strict single inheritance only. 1
- A class can extend another class (e.g.
class A {} ; class B extends A {}), but it cannot extend an interface. (e.g. error code:interface A {} ; class B extends A {}) - In TypeScript, an interface can also extend a class (e.g.
class A {} ; interface B extends A {}), but only in a way that involves inheritance.- (Important) When an interface extends a class, the interface includes all class members (public and private) but not the class implementation. 2
Implementation
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function applyMixins(derivedConstructor: any, baseConstructors: any[]) {
baseConstructors.forEach(baseConstructor => {
Object.getOwnPropertyNames(baseConstructor.prototype).forEach(name => {
if (name !== 'constructor') {
Object.defineProperty(
derivedConstructor.prototype,
name,
Object.getOwnPropertyDescriptor(baseConstructor.prototype, name) ||
Object.create(null),
);
}
});
});
}
Usage
Used as follows, it works within a single file.
class c0 {
a: number;
constructor(a: number) {
this.a = a;
}
get val() {
return this.a;
}
}
class c1 extends c0 {
get first() {
return this.val + 1;
}
}
class c2 extends c0 {
get second() {
return this.val + 2;
}
}
class c3 extends c0 {
b: number;
constructor() {
super(300);
this.b = 200;
}
get third() {
return this.val + 3;
}
}
interface c3 extends c1, c2 {
// EMPTY.
}
applyMixins(c3, [c1, c2]);
export default c3;
const temp = new c3();
console.debug(temp.a);
console.debug(temp.first);
console.debug(temp.second);
console.debug(temp.third);
console.debug(temp.b);
Troubleshooting
TS2310: recursively references itself as a base type.
If you export it for use outside the file, the following error is printed.
It is most likely a caching problem. If you are using something like an IDE, try rebooting it.
See also
- mixins
- typescript
Favorite site
- TypeScript: Documentation - Mixins
- Mixins - TypeScript Deep Dive
- Introduction to Mixins in TypeScript
- extends and implements | MJ Kim
- Mixins · GitBook
References
Pages that link here