클래스 위에다가 데코레이터를 작성을 하면 파라미터로 데코레이팅 한 대상 클래스를 받아볼 수 있다.
@Test
@Frozen
@LogTest('실행')
@ChangeClass
class Idol {
name: string;
age: number;
constructor(name: string, age: number){
this.name = name;
this.age = age;
}
}
function Test(constructor: Function){
console.log(constructor);
// 실제 Idol 클래스 정의가 constructor라는 파라미터로 입력된다.
}
Idol 클래스의 데코레이터로 Test가 있다.
Test라는 데코레이터가 실행이 되면서 Test 함수를 실행을 한다.
이 때 constructor라는 파라미터에 Idol 클래스를 받는다.
function Frozen(constructor: Function){
Object.freeze(constructor);
Object.freeze(constructor.prototype);
}
마찬가지로 Idol 클래스의 Frozen 데코레이터가 있다.
Frozen이라는 데코레이터가 실행이 되면서 Frozen 함수를 실행한다.
이 때 constructor에 Idol클래스를 받고 Idol클래스를 얼린다.
데코레이터 팩토리는 데코레이팅을 할 때 파라미터를 받을 수 있다.
function LogTest(env: string){
return function(constructor: Function){
console.log(`${env} ${constructor}생성자 실행`);
}
}
마찬가지로 LogTest라는 데코레이터가 있다. 하지만 이전과 다른 점은 함수로 표시하여 안에 '실행'이라는 값을 넣어주고 있다. 그러면 LogTest에서 env에 '실행'이 들어오고 마찬가지로 constructor변수에 Idol클래스가 들어온다.
function ChangeClass<T extends {new(...args: any[]): {}}>(constructor: T){ //T타입의 constructor는 인스턴스화 할 수 있는 constructor이다.
return class extends constructor{
groupName = '아이브';
constructor(...params: any[]){
super(...params);
console.log('asdasd');
}
}
}
<T extends {new(...args: any[]): {}}> 이것을 통해 T 타입은 인스턴스화 할 수 있는 constructor가 되었다. 그리고 constructor가 확장된 클래스를 리턴한다.