TypeScript 데코레이터 이해

14364 단어 typescriptprogramming


데코레이터는 클래스와 해당 멤버(메서드, 속성)를 수정하는 데 사용됩니다.
문제는 이러한 것들을 변경하기 위해 데코레이터가 필요한 이유가 될 수 있습니다. 선언을 직접 변경하지 않는 이유는 무엇입니까?

직접 변경은 확장할 수 없습니다. 100개의 클래스에 동일한 변경이 필요한 경우 100번 작성해야 합니다. 데코레이터를 사용하면 한 번 작성하고 원하는 만큼 여러 번 적용할 수 있습니다.

데코레이터는 작업하기 쉬운 중심점을 제공합니다. NestJS , Angular 와 같은 프레임워크는 데코레이터를 광범위하게 사용합니다.

TypeScript에서는 다음을 꾸밀 수 있습니다.
  • 클래스
  • 방법
  • 재산
  • 접속자
  • 매개변수

  • 데코레이터는 TypeScript 기능이며 아직 JavaScript에 공식적으로 포함되지 않았습니다. 그러나 향후 추가될 가능성이 높습니다(현재 2단계).

    클래스 데코레이터



    // The following decorator makes any class more Funky
    function makeFunky(target: Function) {
        return class extends target {
            constructor() {
                super()
            }
            funkIt() {
                console.log("Get The Funk Outta My Face")
                }
            }
        }
    }
    
    @makeFunky
    class Car {
        wheels = 4
        state = 'pause'
        drive() {
            this.state = 'running'
        }
    }
    
    const car = new Car()
    car.funkIt()
    // logs: Get The Funk Outta My Face
    

    데코레이터는 함수일 뿐이며 makeFunky는 위의 데코레이터입니다. makeFunky는 적용되는 클래스Car를 매개변수로 가져옵니다. 원래 클래스의 수정된 버전인 새 클래스를 반환합니다.

    데코레이터는 객체가 인스턴스화될 때가 아니라 클래스가 선언될 때 호출됩니다.

    메서드 데코레이터



    메소드에 적용된 데코레이터는 다음 매개변수를 가져옵니다.

  • target : 정적 메서드의 경우 target는 클래스의 생성자 함수입니다. 인스턴스 메서드의 경우 target는 클래스의 프로토타입입니다.

  • propertyKey : 메서드의 이름입니다.

  • descriptor : 메서드의 속성 설명자

  • function log(target: Object, propertyKey: string, descriptor: PropertyDescriptor) {
        const originalMethod = descriptor.value
        descriptor.value = function () {
            console.log('arguments are ', arguments)
            const result = originalMethod.apply(this, arguments)
            console.log(`result is ${result}`)
            return result
        }
    }
    
    class Calculator {
        @log
        add(x: number, y: number): number {
            return x + y
        }
    }
    
    const calc = new Calculator()
    calc.add(10, 20)
    
    /*
    [LOG]: "arguments are ",  {
      "0": 10,
      "1": 20
    } 
    [LOG]: "result is 30" 
    */
    

    속성 데코레이터



    메서드 데코레이터와 비슷합니다. 메서드 데코레이터와 동일한 매개 변수 target , propertyKeydescriptor를 가져옵니다. 반환 값은 무시됩니다.

    function logMutation(target: any, key: string ) {
        var _val = target[key]
        Object.defineProperty(target, key, {
            set: function(newVal) {
                console.log('new value is ' + newVal)
                _val = newVal
            },
            get: function() {
                    return _val
                }
            })
    }
    
    class Person {
        @logMutation
        public age: number
    
        constructor(age: number) {
            this.age = age
        }
    }
    
    const jack = new Person(20)
    jack.age = 40
    
    /*
    [LOG]: "new value is 20" 
    [LOG]: "new value is 40" 
    */
    


    접근자와 매개변수 데코레이터



    접근자 데코레이터는 메서드 데코레이터와 동일하지만 단일 멤버의 getter 또는 setter 메서드에 적용됩니다.

    매개변수 데코레이터는 매개변수에 적용됩니다.

    데코레이터 팩토리



    데코레이터 사용의 일반적인 패턴은 데코레이터를 반환하는 함수를 호출하는 것입니다. 다음은 함수 로거를 호출하여 반환된 이전에 언급한 메서드 데코레이터log입니다.

    function logger(functionName: string) {
        function log(target: Object, propertyKey: string, descriptor: PropertyDescriptor) {
            const originalMethod = descriptor.value
            descriptor.value = function () {
                console.log('method name: ' + functionName)
                console.log('arguments are ', arguments)
                const result = originalMethod.apply(this, arguments)
                console.log(`result is ${result}`)
                return result
            }
        }
        return log
    }
    
    class Calculator {
        @logger('add')
        add(x: number, y: number): number {
            return x + y
        }
    }
    
    const calc = new Calculator()
    calc.add(10, 20)
    
    /*
    [LOG]: "method name: add" 
    [LOG]: "arguments are ", {
      "0": 10,
      "1": 20
    } 
    [LOG]: "result is 30" 
    */
    


    야생의 데코레이터



    데코레이터의 일부 사용 사례는 인기 있는 라이브러리/프레임워크에서 활용됩니다.

  • NestJS는 클래스 데코레이터@Controller('pathName')를 사용하여 클래스를 컨트롤러로 정의합니다. 데코레이터는 클래스를 필수 메타데이터와 연결하고 Nest가 라우팅 맵을 생성할 수 있도록 합니다(요청을 해당 컨트롤러에 연결). 또한 데코레이터를 사용하여 의존성 주입 시스템을 위한 주입 가능한 인스턴스인 모듈을 정의합니다.

  • TypeORM은 데코레이터를 사용하여 클래스를 엔티티로 정의@Entity(), 속성을 열로 태그 지정@Column(), 자동 증가 ID 등
  • NPM 패키지 class-validator는 객체의 속성을 검증하는 데 사용됩니다(수입 데이터, 함수 인수와 같은 검증에 사용됨). 특정 필드에 대한 제한을 설정하기 위해 @IsInt() @Min(5) @Max(25)와 같은 데코레이터가 있습니다.
  • 좋은 웹페이지 즐겨찾기