소개
- TypeScript 및 ES6에 클래스가 도입되면서 클래스 및 클래스 멤버에 주석(annotation)을 달거나 수정하기 위해 추가 기능이 필요한 특정 시나리오가 있습니다.
- 데코레이터는 클래스 선언과 멤버에 대한 주석(annotation)과 메타 프로그래밍 구문을 모두 추가 할 수있는 방법을 제공합니다.
- 정말 개꿀
- 데코레이터는 JavaScript에 대한 2단계 제안이며 TypeScript의 실험 기능으로 제공됩니다.
참고 데코레이터는 향후 릴리스에서 변경 될 수있는 실험적인 기능입니다. ( Nest.js 같은 서버 프레임워크에서 정말 애용하는 문법이다. 고로, 없어질 가능성은 엄청나게 적으며 없어진다는 발표가 나면 엄청난 반발을 사게 될 것 이다. )
- 데코레이터에 대한 실험 지원을 활성화하려면 명령 행 또는 tsconfig.json에서 ExperimentDecorators 컴파일러 옵션을 활성화해야합니다.
- Nest.js 프로젝트의 tsconfig.json 파일에 아주 자랑스럽게 명시되어 있다. => 개꿀
커멘드 라인
tsc --target ES5 --experimentalDecorators
tsconfig.json
{
"compilerOptions": {
"target": "ES5",
"experimentalDecorators": true
}
}
데코레이터(Decorators)
- 데코레이터는 class declaration, method, accessor, property또는 parameter.에 첨부 할 수있는 특수한 종류의 선언입니다.
- 데코레이터는 @expression 형식을 사용합니다. 여기서 expression은 데코레이트 된 선언에 대한 정보와 함께 런타임에 호출 될 함수로 평가되어야합니다.
- 예를 들어, 데코레이터 @sealed를 사용하면 다음과 같이 sealed 밀봉 함수를 작성할 수 있습니다.
function sealed(target) {
// do something with 'target' ...
}
참고, 아래의 Class Decorators에서 데코레이터에 대한 자세한 예를 볼 수 있습니다.
데코레이터 팩토리(Decorator Factories)
- 데코레이터가 선언에 적용되는 방식을 사용자 정의하고 싶다면, 데코레이터 팩토리를 작성하여도 좋습니다.
- 데코레이터 팩토리는 단순히 데코레이터가 런타임에 호출 할 표현식을 반환하는 함수입니다.
- 다음과 같은 방식으로 데코레이터 팩토리를 작성할 수 있습니다.
function color(value: string) { // this is the decorator factory
return function (target) { // this is the decorator
// do something with 'target' and 'value'...
}
}
참고, 아래 Method Decorators에서 데코레이터 팩토리에 대한 자세한 예를 볼 수 있습니다.
데코레이터 컴포지션
- 다음 예제와 같이 선언에 여러 데코레이터를 적용 할 수 있습니다.
한 줄 적용
@f @g x
여러줄 적용
@f
@g
x
- 여러 데코레이터가 단일 선언에 적용되는 경우 평가는 function composition in mathematics과 유사합니다.
- 이 모델에서 함수 f와 g을 구성 할 때 결과 합성 (f ∘ g) (x)은 f( g(x))와 같습니다.
- 따라서 TypeScript의 단일 선언에서 여러 데코레이터를 평가할 때 다음 단계가 수행됩니다.
- 각 데코레이터의 평가는 위에서 아래로 평가됩니다.
- 그런 다음 결과는 아래에서 위로 함수가 호출됩니다.
- decorator factories를 사용하는 경우 다음 예제를 통해이 평가 순서를 관찰 할 수 있습니다.
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
데코레이터 평가
클래스 내부의 다양한 선언에 적용된 데코레이터가 적용되는 방법에는 잘 정의 된 순서가 있습니다.
- 매개 변수 데코레이터 뒤에 오는 메소드, 접근자 또는 프로퍼티 데코레이터는 각 인스턴스 멤버에 적용됩니다.
- 매개 변수 데코레이터 뒤에 오는 메소드, 접근자 또는 프로퍼티 데코레이터는 각 정적 멤버에 적용됩니다.
- 매개 변수 데코레이터는 생성자에 적용됩니다.
- 클래스 데코레이터는 클래스에 적용됩니다.
클래스 데코레이터(Class Decorators)
- 클래스 데코레이터는 클래스 선언 직전에 선언됩니다.
- 클래스 데코레이터는 클래스의 생성자에 적용되며 클래스 정의를 관찰, 수정 또는 교체하는 데 사용할 수 있습니다.
- 클래스 데코레이터는 선언 파일 또는 다른 주변 환경(예 : 선언 클래스)에서 사용할 수 없습니다.
- 클래스 데코레이터의 표현식은 런타임에 함수로 호출되며 데코레이트 된 클래스의 생성자는 유일한 인수로 사용됩니다.
- 클래스 데코레이터가 값을 반환하면 클래스 선언을 제공된 생성자 함수로 바꿉니다.
참고, 새 생성자 함수를 반환하도록 선택한 경우 원래 프로토 타입을 유지 관리해야합니다. 런타임시 데코레이터를 적용하는 로직은이를 수행하지 않습니다.
- 다음은 Greeter 클래스에 적용된 클래스 데코레이터 (@sealed)의 예입니다.
@sealed
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
}
- 다음 함수 선언을 사용하여 @sealed 데코레이터를 정의 할 수 있습니다.
function sealed(constructor: Function) {
Object.seal(constructor);
Object.seal(constructor.prototype);
}
- @sealed가 실행되면 생성자와 프로토 타입이 모두 봉인됩니다.
- 다음으로 생성자를 재정의하는 방법에 대한 예제가 있습니다.
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"));
알아야하는 게 있어지면 또 정리....
'Javascript > Typescript' 카테고리의 다른 글
타입스크립트 튜토리얼 - 리액트 & 웹펙 묶기 (0) | 2020.01.30 |
---|---|
타입스크립트 핸드북 - 클래스 (0) | 2020.01.30 |
타입스크립트 핸드북 - 인터페이스 (0) | 2020.01.29 |
타입스크립트 핸드북 - 변수선언 (0) | 2020.01.29 |
타입스크립트 핸드북 - 기본 자료형 (0) | 2020.01.26 |