(TS) 데코레이터 1️⃣

  • by


🍒 (230320 TIL) Understanding TypeScript

Decorators 1️⃣

What is Decorators?

클래스, 프로퍼티, 액세서, 메소드, 파라미터에 첨부할 수 있는 특별한 함수이다.

데코레이터가 붙은 클래스 등에서는 데코레이터로 정의된 기능이 동작한다.

정의한 데코레이터 함수 @ 기호를 붙여 실행할 수 있다.

function ClassDeco(constructor: Function) {
    console.log('Logging...');
    console.log(constructor);
}

@ClassDeco
class Person {
    name="Shou";
    
    constructor() {
        console.log('Creating person object...');
    }
}
/* Logging...
   class Person {
       constructor() {
           this.name="Shou";
           console.log('Creating person object...');
       }
   } */

데코레이터는 인스턴스가 생성되지 않고 클래스 정의에서만 실행됩니다.

데코레이터 팩토리

데코레이터는 특정 객체에 데코레이터를 할당할 때 설정할 수 있도록 팩토리를 정의할 수 있습니다.

팩토리 함수에서 실행하면 장식 함수가 사용하는 값을 사용자 정의할 수 있습니다.

function ClassDeco(logString: string) {
    return function(constructor: Function) {
        console.log(logString);
        console.log(constructor);
    }
}

@ClassDeco('Logging - Person')
class Person {
    name="Shou";
    
    constructor() {
        console.log('Creating person object...');
    }
}
/* Logging - Person
   class Person {
       constructor() {
           this.name="Shou";
           console.log('Creating person object...');
       }
   } */

Composition

다양한 데코레이터를 함께 사용할 수 있습니다.

데코레이터를 여러 개 사용하는 경우 다음과 같이 하십시오.

  1. 각 데코레이터의 표현은 위에서 아래로 평가됩니다.

  2. 평가 후 결과는 아래에서 위의 함수로 호출됩니다.

function F(key: string) {
    console.log("evaluate: ", key);
    return function() {
        console.log("call: ", key);
    }
}

class C {
    @F('first')
    @F('second')
    method() {}
}

/*
evaluate: first
evaluate: second
call: second
evaluate: first
*/

클래스 데코레이터

function ClassDeco(constructor: Function) {
    console.log('Class decorator');
    console.log(constructor);
}

@ClassDeco
class Person {
    name="Shou";
    
    get name() {
        return this.name;
    }
    
    constructor() {
        console.log('Creating person object...');
    }
    
    getName(intro: string) {
        console.log(intro, this.name);
    }
}

Property decorator

function PropertyDeco(target: any, propertyKey: string | Symbol) {
    console.log('Property decorator');
    console.log(target, propertyKey);
}

class Person {
    @PropertyDeco
    name="Shou";
    
    get name() {
        return this.name;
    }
    
    constructor() {
        console.log('Creating person object...');
    }
    
    getName(intro: string) {
        console.log(intro, this.name);
    }
}

액세서 데코레이터

function AccessorDeco(
    target: any,
    propertyKey: string | Symbol,
    descriptor: PropertyDescriptor
) {
    console.log('Accessor decorator');
    console.log(target, propertyKey, descriptor);
}

class Person {
    name="Shou";
    
    @AccessorDeco
    get name() {
        return this.name;
    }
    
    constructor() {
        console.log('Creating person object...');
    }
    
    getName(intro: string) {
        console.log(intro, this.name);
    }
}

메소드 데코레이터

function MethodDeco(
    target: any,
    propertyKey: string | Symbol,
    descriptor: PropertyDescriptor
) {
    console.log('Method decorator');
    console.log(target, propertyKey, descriptor);
}

class Person {
    name="Shou";
    
    get name() {
        return this.name;
    }
    
    constructor() {
        console.log('Creating person object...');
    }
    
    @MethodDeco
    getName(intro: string) {
        console.log(intro, this.name);
    }
}

파라미터 데코레이터

function ParameterDeco(
    target: any,
    propertyKey: string | Symbol,
    parameterIndex: number
) {
    console.log('Method decorator');
    console.log(target, propertyKey, descriptor);
}

class Person {
    name="Shou";
    
    get name() {
        return this.name;
    }
    
    constructor() {
        console.log('Creating person object...');
    }
    
    getName(@ParameterDeco intro: string) {
        console.log(intro, this.name);
    }
}