이 글은 PC 버전 TISTORY에 최적화 되어있습니다.
서론
모든 데코레이터는 그냥 Function이고 그냥 Function의 이름을 가져다 불러 쓰면 됩니다.
1. Class Decorator2. MethodDecorator3. Property Decorator4. Parameter Decorator
Class Decorator
function hello(constructorFn: Function) {
console.log(constructorFn);
}
@hello
class Person {
}
1. 딱히 클래스 인스턴스를 만들지 않아도 접근 가능하다.
2. 인자로 constructor Function을 가져가는데(class Decorator의 signature이므로 무조건 넣기) Person의 constructor Function이 들어감
이렇게는 많이 안씀 Decorator를 Factory로 사용하는 방법
function hello(constructorFn: Function) {
console.log(constructorFn);
}
function helloFactory(show: boolean) {
// 인자를 받고 hello를 실행하거나 실행하지 않거나
if (show) {
return hello; // hello Decorator 함수를 쓴다.
} else {
return null; // 아무 데코레이터 함수를 사용하지 않는다.
}
}
@helloFactory(true) // 보여줄래
@helloFactory(false) // 안보여줄래
class Person {
}
Advanced Class Decorator
이번 목표는 hello를 추가하는데 hello가 어노테이션 되어있는 클래스는 hello 메소드를 추가해줄 것이다.
function hello(constructorFn: Function) {
constructorFn.prototype.hello = function() {
console.log("hello");
}
}
@hello
class Person {
}
const p = new Person();
p.hello(); // error 실제로 없고 다른 방법으로 추가됬기 때문에
(<any>p).hello(); // hello - ??? 왜 이렇게 해야하는지 추후에 업데이트 하겠습니다.
Method Decorator
수정 불가능한 메소드를 만들어 보겠습니다.
function editable(isEditable: boolean) {
return function(target: any, propName: string, description: PropertyDescriptor) {
console.log(target); // Person { }
console.log(propName); // hello
console.log(description);
// ES6 definePoroperty(target, propName, description) 참고 3번째 옵션과 같다.
description.writable = isEditable;
}
}
class Person {
constructor() {
console.log("new Person()");
}
@editable(false)
hello() {
console.log("hello");
}
}
const person = new Person();
person.hello(); // hello
person.hello = function() {
console.log("world");
}
person.hello(); // hello
Property Decorator
property decorator는 property 선언 전에 선언합니다. function과 마찬가지로 런타임에 실행됩니다. 다음의 두 인자와 함께 말이죠.
function writable(canBeWritable: boolean) {
return function(target: any, propName: string): any{
console.log(target); // Person { }
console.log(propName); // name
// 얘가 description 역할
return {
writable: isWritable
};
}
}
class Person {
@writable(false);
name: string = "Mark";
constructor() {
console.log("new Person()");
}
}
const p = new Person();
console.log(p.name); // Mark라는 것을 readonly Property에 넣어서 에러
Parameter Decorator
function printInfo(target: any, methodName: string, paramIndex: number) {
console.log(target); // 1. ctor: [Function: Person] 2. helloFunc: Person { }
console.log(methodName); // 1. ctor: undefined 2. helloFunc: hello
console.log(paramIndex); // 1. ctor: 1 2. helloFunc: 0
}
class Person {
private _name: string;
private _age : number;
constructor(name: string, @printInfo age: number) {
this._name = name;
this._age = age;
}
hello(@printInfo message: string) {
console.log("message");
}
}
// const p = new Person("Evan", "27");
반응형
'Basic > Typescript' 카테고리의 다른 글
[Typescript] Index Signatures(Indexable types) (1) | 2018.01.01 |
---|---|
[Typescript] Class를 통한 구조적 추상화 (0) | 2017.12.22 |
[Typescirpt] Class 알아보기 (0) | 2017.12.22 |
[Typescript] 미래의 자바스크립트 (0) | 2017.12.22 |