-
Typescript 5.0 업데이트에서 달라진 것들 - DecoratorsTypescript 2023. 4. 9. 16:13
- Decorators
- const Type Parameters
- Supporting Multiple Configuration Files in extends
- All enums Are Union enums
- --moduleResolution bundler
- Resolution Customization Flags
- --verbatimModuleSyntax
모든 링크들은 원문을 가리킵니다.
Decorators
데코레이터는 클래스와 멤버를 재사용 가능한 방식으로 사용자 정의할 수 있게 해주는 곧 출시될 ECMAScript 기능입니다.
class Person { name: string; constructor(name: string) { this.name = name; } greet() { console.log(`Hello, my name is ${this.name}.`); } } const p = new Person("Ron"); p.greet();
greet은 매우 간단하지만 훨씬 더 복잡한 것이라고 상상해 봅시다. 비동기 로직을 수행하고 재귀 함수가 있고, 부작용이 있을 수 있다고 생각 해봅시다. 그런 상황에서 디버깅을 위해서 console.log()를 사용합니다.
class Person { name: string; constructor(name: string) { this.name = name; } greet() { console.log("LOG: Entering method."); console.log(`Hello, my name is ${this.name}.`); console.log("LOG: Exiting method.") } }
위와 같은 부분들을 데코레이터가 대신 해줄 수 있습니다.
logMethod라는 함수를 작성할 수 있습니다.
function loggedMethod(originalMethod: any, context: ClassMethodDecoratorContext) { const methodName = String(context.name); function replacementMethod(this: any, ...args: any[]) { console.log(`LOG: Entering method '${methodName}'.`) const result = originalMethod.call(this, ...args); console.log(`LOG: Exiting method '${methodName}'.`) return result; } return replacementMethod; } class Person { name: string; constructor(name: string) { this.name = name; } @loggedMethod greet() { console.log(`Hello, my name is ${this.name}.`); } } const p = new Person("Ron"); p.greet(); // Output: // // LOG: Entering method. // Hello, my name is Ron. // LOG: Exiting method.
TypeScript는 메서드 데코레이터가 사용하는 컨텍스트 개체를 모델링하는 ClassMethodDecoratorContext라는 유형을 제공합니다.
또한, addInitializer를 사용하여 생성자에서 바인딩을 호출하는 데코레이터를 작성할 수 있습니다.
function bound(originalMethod: any, context: ClassMethodDecoratorContext) { const methodName = context.name; if (context.private) { throw new Error(`'bound' cannot decorate private properties like ${methodName as string}.`); } context.addInitializer(function () { this[methodName] = this[methodName].bind(this); }); } class Person { name: string; constructor(name: string) { this.name = name; } @bound @loggedMethod greet() { console.log(`Hello, my name is ${this.name}.`); } } const p = new Person("Ron"); const greet = p.greet; // Works! greet();
@bound 및 @loggedMethod라는 2개의 데코레이터를 사용 했습니다.
실행 순서는 "역순" 입니다.
또한, logMethod가 데코레이터를 반환하도록 하고 메시지를 기록하는 방법을 사용자 정의할 수 있습니다.
function loggedMethod(headMessage = "LOG:") { return function actualDecorator(originalMethod: any, context: ClassMethodDecoratorContext) { const methodName = String(context.name); function replacementMethod(this: any, ...args: any[]) { console.log(`${headMessage} Entering method '${methodName}'.`) const result = originalMethod.call(this, ...args); console.log(`${headMessage} Exiting method '${methodName}'.`) return result; } return replacementMethod; } } class Person { name: string; constructor(name: string) { this.name = name; } @loggedMethod("") greet() { console.log(`Hello, my name is ${this.name}.`); } } const p = new Person("Ron"); p.greet(); // Output: // // Entering method 'greet'. // Hello, my name is Ron. // Exiting method 'greet'.
experimentalDecorators는 당분간 계속 존재할 것입니다.
그러나 플래그가 없으면 데코레이터는 이제 모든 새 코드에 유효한 구문이 됩니다.
export 키워드 앞에 데코레이터를 추가할 수 있습니다.
기본값 뒤에도 데코레이터를 배치할 수 있습니다.
유일하게 안되는 것은 혼합 허용은 되지 않는다는 점입니다.
// allowed @register export default class Foo { // ... } // also allowed export default @register class Bar { // ... } // error - before *and* after is not allowed @before export @after class Bar { // ... }
위의 loggingMethod 및 바인딩된 데코레이터 예제는 의도적으로 단순하며 유형에 대한 많은 세부 정보를 생략합니다.
입력 데코레이터는 상당히 복잡할 수 있습니다. 예를 들어, 위의 logMethod의 올바른 유형 버전은 다음과 같습니다.
function loggedMethod<This, Args extends any[], Return>( target: (this: This, ...args: Args) => Return, context: ClassMethodDecoratorContext<This, (this: This, ...args: Args) => Return> ) { const methodName = String(context.name); function replacementMethod(this: This, ...args: Args): Return { console.log(`LOG: Entering method '${methodName}'.`) const result = target.call(this, ...args); console.log(`LOG: Exiting method '${methodName}'.`) return result; } return replacementMethod; }
This, Args 및 Return 유형 매개변수를 사용하여 this 유형, 매개변수 및 원래 메서드의 반환 유형을 별도로 모델링해야 했습니다.
데코레이터 함수가 정확히 얼마나 복잡하게 정의되어 있는지는 보장하려는 항목에 따라 다릅니다.
데코레이터는 작성된 것보다 더 많이 사용되므로 일반적으로 타이핑이 잘 된 버전이 바람직하지만 가독성과 상쇄되므로 적절하게 타협해서 작업 하세요.
다음 시간에는 const type parameters에 대해서 알아보도록 하겠습니다.
출처 : https://devblogs.microsoft.com/typescript/announcing-typescript-5-0/
'Typescript' 카테고리의 다른 글
TypeScript 시작 방법 (0) 2021.04.29