studye / typescript

타입스크립트는 자바스크립트랑 다른 언어인가요?
7 stars 0 forks source link

[Chapter 4] Decorators #20

Open laziel opened 7 years ago

laziel commented 7 years ago

Class decorator parameters

클래스 데코레이터는 constructor 함수를 파라미터로 받아 생성자에 관여한다.

function classConstructorDec(constructor: Function) {
   constructor.prototype.testProperty = "oh yeah";
}

@classConstructorDec
class ClassWithConstructor { ... }

let a = new ClassWithConstructor(); 
console.log(a.testProperty); // oh yeah

Property decorators

프로퍼티 데코레이터 함수에는 클래스 프로토타입과 프로퍼티 이름(string)이 파라미터로 제공된다. 프로퍼티 데코레이터는 클래스 인스턴스에 특정 프로퍼티가 선언되었는지 확인할 수 있게 한다. 참조: https://www.typescriptlang.org/docs/handbook/decorators.html#property-decorators

static property 에 대해서도 데코레이터를 사용할 수 있다. 단, 이 때에는 데코레이터 함수의 첫 번째 파라미터가 클래스 프로토타입이 아닌 클래스 생성자(constructor)가 된다.

Method decorators

메소드 데코레이터 함수에는 클래스 프로토타입, 메소드 이름, 메소드 descriptor (optional) 가 파라미터로 제공된다. 데코레이터 함수는 대상 메소드를 호출할 때 마다 항상, 그리고 먼저 호출된다.

function enumerable(value: boolean) {
    return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
        descriptor.enumerable = value;
        console.log(descriptor.value()); // Hello, undefined
    };
}

class Greeter {
    greeting: string;
    constructor(message: string) {
        this.greeting = message;
    }

    @enumerable(false)
    greet() {
        return "Hello, " + this.greeting;
    }
}

Parameter decorators

파라미터 데코레이터 함수에는 클래스 프로토타입, 메소드명, 파라미터 인덱스가 파라미터로 제공된다.

laziel commented 7 years ago

TypeScript source:

function testdec(target: any, key: string) {
    console.log('this is decorator');

    if (key === 'message') {
        target[key] = 'asdf';
    }
}

class test {
    @testdec
    message: string;

    constructor(message) {
        this.message = this.message || message;
    }

    @testdec
    test() {
        console.log('this is method test()');
    }
}

var a = new test('qwer');

a.test();
console.log('property message: ', a.message);

transpiled as JavaScript:

var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
function testdec(target, key) {
    console.log('this is decorator');
    if (key === 'message') {
        target[key] = 'asdf';
    }
}
var test = (function () {
    function test(message) {
        this.message = this.message || message;
    }
    test.prototype.test = function () {
        console.log('this is method test()');
    };
    return test;
}());
__decorate([
    testdec
], test.prototype, "message", void 0);
__decorate([
    testdec
], test.prototype, "test", null);
var a = new test('qwer');
a.test();
console.log('property message: ', a.message);

결과:

this is decorator
this is decorator
this is method test()
property message:  asdf