TypeScript에서 decorator
기능을 이용하기 위해서는 tsconfig에서 experimentalDecorators
속성을 활성화 해야 한다.
target
클래스의 선언부에 쓰였을 경우, 클래스의 생성자 함수가 들어온다.
decorator
함수 내에서 클래스의 생성자 함수를 변형하여 반환한다면, decorator
가 적용된 클래스의 생성자 함수가 이에 따라 변형된다.
데코레이터를 이용해 싱글톤을 구현한 예시는 다음과 같다.
function singleton<T extends { new (...args: any[]): {} }>(target: T) {
let instance: T | null = null;
return class extends target {
constructor(...args: any[]) {
if (instance) {
return instance;
}
super(...args);
instance = this as unknown as T;
}
};
}
@singleton
class DemoClass {
constructor(private name: string) {}
getName() {
return this.name;
}
}
const demo = new DemoClass("a");
console.log(demo.getName());
const demo2 = new DemoClass("b");
console.log(demo2.getName());
메서드 데코레이터의 경우 정적 메서드일 때 클래스의 생성자함수가, 인스턴스 메서드일 때 클래스의 프로토타입 객체가 들어온다.
property key
decorator
가 적용된 요소의 이름을 나타낸다.
메서드 데코레이터의 경우
메서드의 이름이 들어온다.
property descriptor
decorator
가 적용된 요소의 property descriptor
객체를 나타낸다.
메서드 데코레이터의 경우 해당 메서드의 property descriptor가 들어온다.
function autobind(_: any, _2: any, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
const newDescriptor: PropertyDescriptor = {
enumerable: false,
configurable: true,
get() {
return originalMethod.bind(this);
},
};
return newDescriptor;
}
class DemoClass {
message = "NAME";
@autobind
getName() {
console.log(this.message);
}
}
const demo = new DemoClass();
const button = document.getElementById("button")!;
button.addEventListener("click", demo.getName);