TypeScript:Mixins
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(그리고 JavaScript) 클래스는 엄격하게 단일 상속만 지원합니다. 1
- 클래스는 다른 클래스를 확장할 수도 있지만(e.g.
class A {} ; class B extends A {}
) 인터페이스는 확장할 수 없습니다. (e.g. 에러 코드:interface A {} ; class B extends A {}
) - TypeScript에서 인터페이스는 클래스를 확장할 수도 있지만(e.g.
class A {} ; interface B extends A {}
) 상속을 포함하는 방식으로만 가능합니다.- (중요) 인터페이스가 클래스를 확장할 때 인터페이스는 모든 클래스 멤버(공개 및 비공개)를 포함하지만 클래스 구현은 포함하지 않습니다. 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
다음과 같이 사용하면 하나의 파일에서는 성공한다.
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.
파일 외부에서 사용하기 위해 export
하면 다음과 같은 에러가 출력된다.
캐싱문제일 가능성이 높다. IDE 같은걸 사용한다면 재부팅해보자.
See also
- mixins
- typescript
Favorite site
- TypeScript: Documentation - Mixins
- 믹스인(Mixin) - TypeScript Deep Dive
- Introduction to Mixins in TypeScript
- extends와 implements | MJ Kim
- 믹스인 · GitBook