www.notion.so/Decorators-ee9928ba4a0b4c5584ddaf478e3910ee
Mark Lee 님의 영상과 자료를 참고하였다.
<Class Decorator example 1>
데코레이터로 class에 메서드를 추가해줬는데
TS에서 Property 'print' does not exist on type 'Test1'. 라며 타이핑 에러를 낸다.
어쩔 수 없이 as any 로 타입 단언을 해줘야 한다.
function classDecorator<T extends { new (...args: any[]): {} }>(constructorFn: T) {
return class extends constructorFn { // 여기서 target은 decorator를 단 class를 의미함.
constructor(...args: any[]) {
super(args);
}
// print 라는 public 메서드를 추가해줌
public print() {
console.log('this is print');
}
};
}
@classDecorator
class Test1 {}
// 문제는 TS는 print라는 메서드가 있는지 모르기 때문에 type 단언으로 any 처리를 해줬음.
(new Test1() as any).print();
<Class Decorator example 2>
조금 더 복잡한 형태의 class decorator입니다.
function classDecoratorFactory(arg: string) {
return function<T extends { new (...args: any[]): {} }>(constructorFn: T) {
// print2 라는 메서드를 prototype에 설정
constructorFn.prototype.print2 = function() {
console.log('this is print2', arg);
};
// prototype에
constructorFn.prototype.gender = 'male';
return class extends constructorFn {
public name = 'mark';
private _age = 36;
constructor(...args: any[]) {
super(args);
}
public print() {
console.log('this is print', arg);
}
};
};
}
@classDecoratorFactory('what')
class Test2 {}
const test2 = new Test2();
(test2 as any).print(); // this is print what
(test2 as any).print2(); // this is print2 what
console.log(Test2.prototype); // class_1 { constructor: [Function: class_1], print: [Function] }
console.log(test2); // class_1 { name: 'mark', _age: 36 }
console.log(Object.keys(test2)); // [ 'name', '_age' ]
console.log((test2 as any).gender); // male
<Method Decorator example 1>
property Descriptor의 writable을 설정하여 값을 재할당할 수 있는지를 설정할 수 있습니다.
function methodDecoratorFactory(canBeEdit: boolean = false) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
descriptor.writable = canBeEdit;
};
}
class Test4 {
@methodDecoratorFactory()
first() {
console.log("first original");
}
@methodDecoratorFactory(true)
second() {
console.log("second original");
}
@methodDecoratorFactory(false)
third() {
console.log("third original");
}
}
const test4 = new Test4();
// runtime error
test4.first = function () {
console.log("first new");
};
test4.second = function () {
console.log("second new");
};
// runtime error
test4.third = function () {
console.log("third new");
};
<Method Decorator example 2>
특정 조건에 따라 메서드에 조작을 가할 수 있습니다.
이거 정말... 좋군요
function log(show: boolean = true) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const original = descriptor.value; // original에 메서드를 담아두자
descriptor.value = function (...args: any[]) {
show && console.log("start"); // show가 true면 출력
original(...args);
show && console.log("end");
};
};
}
class Test5 {
@log()
print1(first: string, second: number) {
console.log("print1", first, second);
}
@log(false)
print2(first: string, second: number) {
console.log("print2", first, second);
}
}
const test5 = new Test5();
// start/end 출력 됨
test5.print1("mark", 36);
// start/end 출력 안 됨
test5.print2("mark", 36);
<Property Decorator 1>
사용 방법은 쉬운데, return 하는 내용이 Property Descriptor이다.
따라서, property의 속성을 제어할 수 있다. 여기서는 writable을 false로 만들어 readonly로 만들어 보겠다.
function propertyDecorator(target: any, propName: string): any {
console.log(target);
console.log(propName);
return {
writable: false
};
}
class Test6 {
@propertyDecorator
name: string = 'Mark';
}
const test6 = new Test6();
test6.name = 'Anna'; // runtime error
<Property Decorator example 1 >
생략합니다. 일반적인 사용법이라.
'Programming Language > 🟦 Typescript' 카테고리의 다른 글
Mapped Type (0) | 2021.03.01 |
---|---|
@Decorator (3) : reflect-metadata (0) | 2021.01.13 |
@Decorator (1) : setting, decorator signature, decorator factory (0) | 2021.01.13 |
ts 환경에서 외부 라이브러리 사용시 주의할 점 (+ typeRoots, esmoduleinterop) (0) | 2020.11.21 |
tsconfig baseUrl 옵션에 의한 오류 바로잡기 (0) | 2020.11.03 |