Open farmeter opened 4 years ago
Command Line
tsc --target ES5 --experimentalDecorators
tsconfig.json
{ "compilerOptions": { "target": "ES5", "experimentalDecorators": true } }
@expression
expression
function sealed(target) { // 'target' 변수와 함께 무언가를 수행합니다. }
이제 @sealed를 사용할 수 있습니다.
@sealed
function color(value: string) { // 데코레이터 팩토리 return function (target) { // 데코레이터 // 'target'과 'value' 변수를 가지고 무언가를 수행합니다. } }
여러 데코레이터를 적용할 수 있습니다.
@f @g x
TypeScript에서 단일 선언에서 여러 데코레이터를 사용할 때 다음 단계가 수행됩니다.
function f() { console.log("f(): evaluated"); return function (target, propertyKey: string, descriptor: PropertyDescriptor) { console.log("f(): called"); } } function g() { console.log("g(): evaluated"); return function (target, propertyKey: string, descriptor: PropertyDescriptor) { console.log("g(): called"); } } class C { @f() @g() method() {} }
f(): evaluated g(): evaluated g(): called f(): called
function sealed(constructor: Function) { Object.seal(constructor); Object.seal(constructor.prototype); //밀봉하여 속성 변경 불가 }
@sealed class Greeter { greeting: string; constructor(message: string) { this.greeting = message; } greet() { return "Hello, " + this.greeting; } } const g = new Greeter("typescript"); delete g.constructor.prototype.greet; delete g.__proto__.greet; //Uncaught TypeError: Cannot delete property 'greet' of #<Greeter>
생성자를 재정의 할수도 있습니다.
function classDecorator<T extends {new(...args:any[]):{}}>(constructor:T) { //생성자를 오버라이드하여 새로운 클래스를 반환 return class extends constructor { newProperty = "new property"; hello = "override"; } } @classDecorator class Greeter { property = "property"; hello: string; constructor(m: string) { this.hello = m; } } console.log(new Greeter("world")); //{property: "property", hello: "override", newProperty: "new property"}
메서드 데코레이터의 표현식은 런타임에 다음 세 개의 인수와 함께 함수로 호출됩니다
메서드 데코레이터가 값을 반환하면, 메서드의 프로퍼티 설명자 로 사용됩니다.
function enumerable(value: boolean) { return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) { descriptor.enumerable = value; }; }
class Greeter { greeting: string; constructor(message: string) { this.greeting = message; } @enumerable(false) greet() { return "Hello, " + this.greeting; } }
접근자 데코레이터는 접근자 선언 바로 전에 선언됩니다.
접근자의 프로퍼티 설명자에 적용되며 접근자의 정의를 관찰, 수정 또는 교체하는 데 사용할 수 있습니다.
표현 식은 런타임에 다음 세 가지 인수와 함께 함수로 호출됩니다
접근자 데코레이터가 값을 반환하면 멤버의 프로퍼티 설명자로 사용됩니다.
function configurable(value: boolean) { return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) { descriptor.configurable = value; }; }
class Point { private _x: number; private _y: number; constructor(x: number, y: number) { this._x = x; this._y = y; } @configurable(false) get x() { return this._x; } @configurable(false) get y() { return this._y; } } const p = new Point(10, 20); console.log(p.x); //10 console.log(p.y); //20
프로퍼티 데코레이터의 표현 식은 런타임에 다음 두 개의 인수와 함께 함수로 호출됩니다
import "reflect-metadata"; // 메타데이터 사용을 위한 reflect-metadata 라이브러리가 필요 // emitDecoratorMetadata 컴파일러 옵션 설정필요 const formatMetadataKey = Symbol("format"); function format(formatString: string) { return Reflect.metadata(formatMetadataKey, formatString); } function getFormat(target: any, propertyKey: string) { return Reflect.getMetadata(formatMetadataKey, target, propertyKey); }
class Greeter { @format("Hello, %s") greeting: string; constructor(message: string) { this.greeting = message; } greet() { let formatString = getFormat(this, "greeting"); return formatString.replace("%s", this.greeting); } }
import "reflect-metadata"; const requiredMetadataKey = Symbol("required"); function required(target: Object, propertyKey: string | symbol, parameterIndex: number) { let existingRequiredParameters: number[] = Reflect.getOwnMetadata(requiredMetadataKey, target, propertyKey) || []; existingRequiredParameters.push(parameterIndex); Reflect.defineMetadata(requiredMetadataKey, existingRequiredParameters, target, propertyKey); }
class Greeter { greeting: string; constructor(message: string) { this.greeting = message; } greet(@required name: string) { return "Hello " + name + ", " + this.greeting; } }
@readonly
@override
https://www.typescriptlang.org/docs/handbook/decorators.html
개요
활성화를 위해선 Command Line 또는 config 수정
Command Line
tsconfig.json
데코레이터 (Decorators)
@expression
형식을 사용합니다.expression
은 데코레이팅 된 선언에 대한 정보와 함께 런타임에 호출되는 함수여야 합니다.이제
@sealed
를 사용할 수 있습니다.데코레이터 팩토리 (Decorator Factories)
데코레이터 합성 (Decorator Composition)
여러 데코레이터를 적용할 수 있습니다.
TypeScript에서 단일 선언에서 여러 데코레이터를 사용할 때 다음 단계가 수행됩니다.
데코레이터 적용 (Decorator Evaluation)
1. 클래스 데코레이터 (Class Decorators)
생성자를 재정의 할수도 있습니다.
2. 메서드 데코레이터 (Method Decorators)
메서드 데코레이터의 표현식은 런타임에 다음 세 개의 인수와 함께 함수로 호출됩니다
메서드 데코레이터가 값을 반환하면, 메서드의 프로퍼티 설명자 로 사용됩니다.
3. 접근자 데코레이터 (Accessor Decorators)
접근자 데코레이터는 접근자 선언 바로 전에 선언됩니다.
접근자의 프로퍼티 설명자에 적용되며 접근자의 정의를 관찰, 수정 또는 교체하는 데 사용할 수 있습니다.
표현 식은 런타임에 다음 세 가지 인수와 함께 함수로 호출됩니다
접근자 데코레이터가 값을 반환하면 멤버의 프로퍼티 설명자로 사용됩니다.
4. 프로퍼티 데코레이터 (Property Decorators)
프로퍼티 데코레이터의 표현 식은 런타임에 다음 두 개의 인수와 함께 함수로 호출됩니다
5. 매개변수 데코레이터 (Parameter Decorators)
요약
@readonly
,@override
등 이미 사용가능한 여러 lib 있음. core-decorators.js기타