클래스 데커레이터는 이름 그대로 클래스 앞에 선언된다.
클래스 데커레이터는 클래스 생성자에 적용되어 클래스의 정의를 읽거나 수정할 수 있다.
말 자체가 쉬우면서도 이해하기 어려운데 다음 예시를 통해 자세히 알아보자.
function reportableClassDecorator<T extends { new (...args: any[]): {} }>(constructor: T) {
return class extends constructor {
reportingURL = "https://example.com";
};
}
@reportableClassDecorator
class BugReport {
type = "report";
title: string;
constructor(t: string) {
this.title = t;
}
}
const bug = new BugReport("Needs dark mode");
console.log(bug);
우선 위에서 부터 차례로 해석하자면,
reportableClassDecorator 함수의 경우에는 클래스 데커레이터 팩토리이다. 이 함수는 아래를 인수로 받는데,
<T extends { new (...args: any[]): {} }>(constructor: T)
의 경우에는 typescript의 문법인데 제너릭 타입 T는 생성자 타입을 상속 받는다는 의미이다.
new (...args: any[]) => {}: 이 부분은 생성자 시그니처를 나타낸다. 이 부분은 생성자 함수의 타입을 의미하며, ...args: any[]는 임의의 개수의 매개변수를 받을 수 있음을 나타낸다. {}는 생성자가 인스턴스를 반환한다는 것을 의미한다.
return class extends constructor { reportingURL = "https://example.com"; }
클래스 데커레이터는 생성자를 리턴해야하는 함수이어야 하므로 생성자를 리턴한다.
그리고 이 클래스에 reportingURL이라는 새로운 속성을 추가해준다.
@reportableClassDecorator class BugReport { type = "report"; title: string; constructor(t: string) { this.title = t; } }
여기에서는 생성자 데커레이터 reportableClassDecorator가 클래스 BugReport에 속성을 추가하거나 읽는다.
마지막으로 콘솔에서는 다음과 같이 찍히게 된다.
{type: 'report', title:'Need dark mode', reportingURL: 'https://example.com'}
클래스에서 선언한 것과 달리 데커레이터의 영향으로 속성에 reportingURL이 추가되었음을 알 수 있다.
추가적으로 이는 클래스의 타입이 바뀌는 것이 아니므로, 타입스크립트 시스템에서는 reportingURL을 인식하지 못한다고 한다.
그래서 bug.reportingURL과 같은 방식으로는 직접사용할 수 없다고 한다.
그렇다면 선언된 클래스에서 reportingURL을 어떻게 사용할 수 있는 건지는 조금 더 알아봐야할 것 같다
우선 차례로 공부하고 있는 입장에서 데커레이터에 대해서 조금은 이해가 된것 같다.
말 그대로 데커레이터의 의미를 갖고 있는 것 같은데 여러가지에 대해서 어떤식으로 decorating을 하는지 컨셉을 잘 이해하는 것이 중요할 것 같다는 생각이 든다.
다음은 method decorator에 대해서 알아보자..
이 포스트는 위 책을 기반으로 작성하고 있습니다...