Mixin is a way that building up classes by combining simpler partial classes.
It is a kind of component reuse.
Basics
It relies on using Generic with class Inheritance to extend a base class.
type Constructor = new (...args: any[]) => {};
class ExClass {
constructor(public name: string) { }
}
function MixinGenerator<T extends Constructor>(Base: T) {
return class Example extends Base {
_age = 1;
setAge(age: number) {
this._age = age;
}
get age(): number {
return this._age;
}
};
}
const MixinClass = MixinGenerator(ExClass);
const mixin = new MixinClass("HoYa");
mixin.setAge(18);
console.log(`Hi, I'm ${mixin.name}. I'm ${mixin.age} years old.`);
// "Hi, I'm HoYa. I'm 18 years old."
In this example, we make a class using mixin.
In other words, we make a mixin class by extending a base class and returning it from the factory function.
Constrained Mixin
Mixin doesn't know about the base class, so it is hard to design a class that we want.
type GenericConstructor<T = {}> = new (...args: any[]) => T;
class ExClass {
constructor(public x: number, public y: number) { }
setCoordinate(x: number, y: number) {
this.x = x;
this.y = y;
}
say() {
console.log(`X: ${this.x}, Y: ${this.y}`);
}
}
type MixinType1 = GenericConstructor<ExClass>;
type MixinType2 = GenericConstructor<{ setCoordinate: (x: number, y: number) => void }>;
type MixinType3 = GenericConstructor<{ say: () => void }>;
function MixinGenerator1<T extends MixinType1>(Base: T) {
return class MixinGenerator1 extends Base {
constructor(...args: any[]) {
super(args[0], args.slice(1));
}
};
}
function MixinGenerator2<T extends MixinType2>(Base: T) {
return class MixinGenerator2 extends Base {
setPoint() {
this.setCoordinate(5, 7);
}
};
}
function MixinGenerator3<T extends MixinType3>(Base: T) {
return class MixinGenerator3 extends Base {
say = () => {
console.log("Hello Mixin");
}
};
}
const MixinClass1 = MixinGenerator1(ExClass);
const MixinClass2 = MixinGenerator2(ExClass);
const MixinClass3 = MixinGenerator3(ExClass);
const mixin1 = new MixinClass1(1, 3);
const mixin2 = new MixinClass2(1, 3);
const mixin3 = new MixinClass3(1, 3);
mixin1.say(); // X: 1, Y: 3
mixin2.setPoint();
mixin2.say(); // X: 5, Y: 7
mixin3.say(); // Hello Mixin
In the above example, it allows for creating classes that only work with the constrained base class.
Then we can create mixins that only work when we have a particular base to build on.
'Web > JavaScript' 카테고리의 다른 글
[Svelte] Lifecycle (0) | 2021.11.12 |
---|---|
[TypeScript] Indexed Access Types, Mapped Types, Conditional Types (0) | 2021.07.09 |
[TypeScript] Generic (0) | 2021.07.05 |
[TypeScript] Singleton Pattern (0) | 2021.07.05 |
[TypeScript] Class (0) | 2021.07.04 |
댓글