TypeScript 装饰器 nest.js 必备

89 阅读3分钟

什么是装饰器?

在 TypeScript 中,装饰器是一种特殊语法,可以用于修饰类、方法、属性和参数。它们通过 @ 语法定义,是由函数实现的。装饰器主要通过元编程机制,为代码提供增强功能。

装饰器的分类

  1. 类装饰器(Class Decorators) :应用于类构造函数,可以用于修改类的定义。
  2. 方法装饰器(Method Decorators) :应用于方法,可以用于修改方法的行为。
  3. 访问器装饰器(Accessor Decorators) :应用于类的访问器属性(getter 或 setter)。
  4. 属性装饰器(Property Decorators) :应用于类的属性。
  5. 参数装饰器(Parameter Decorators) :应用于方法参数。
装饰器名称装饰器描述装饰器的参数说明
类装饰器(Class Decorators)应用于类构造函数,可以用于修改类的定义。constructor: Function
方法装饰器(Method Decorators)应用于方法,可以用于修改方法的行为。target: Object, propertyKey: string, descriptor: PropertyDescriptor
访问器装饰器(Accessor Decorators)应用于类的访问器属性(getter 或 setter)。target: Object, propertyKey: string, descriptor: PropertyDescriptor
属性装饰器(Property Decorators)应用于类的属性。target: Object, propertyKey: string
参数装饰器(Parameter Decorators)应用于方法参数。target: Object, propertyKey: string, parameterIndex: number

装饰器的特点

  • 装饰器是语法糖,本质上是一个函数。
  • 装饰器通常返回一个函数,用来替换或增强目标代码。
  • 装饰器执行的顺序是从下到上,从外到内(从最近作用域开始解析)。

类装饰器

当类装饰器有返回值时,返回的值会替换原有的类的定义。

// @ts-nocheck
function Liu(cls: any) {
    cls.prototype.id = "1";
}

function ReturnDecorator(name: string) {
    console.log('ReturnDecorator');

    return function (target: any) {
        // 这里 target
        console.log(name);
    };
}

@Liu
@ReturnDecorator('lsp')
class Name { }


const name = new Name()
console.log(name.id) // liu

// ReturnDecorator
// lsp
// 1

装饰器工厂

可以传入参数进去

// @ts-nocheck
function Liu(cls: string) {
    // cls hello
    return function (target: any,) {
        // param Name
        target.prototype.liu = cls;
        target.prototype.s = cls;
    };
}

@Liu('hello')
class Name { }
const name = new Name()

console.log(name.liu) // hello
console.log(name.s) // hello

属性装饰器 也可以用作函数

参数3: 成员的属性描述符,详见 descriptor

添加 get 注意 不能直接使用 cls[key] 会无限循环调用的,需要映射

function Log(prefix: string) {

    return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
        const original = descriptor.value;
        descriptor.value = function (...args: any[]) {
            console.log(`${prefix} 调用方法: ${propertyKey}`);
            return original.apply(this, args);
        };
    };
}

class Example {
    @Log("DEBUG")
    sayHello() {
        console.log("Hello, world!");
    }
}

new Example().sayHello();

参数装饰器

// @ts-nocheck
function Liu(num) {
  console.log(num); // 100
  return function (target: any, propertyKey, index) {
    // cls 类型  key: a 参数名字,index: 0 参数索引
    console.log(target, propertyKey, index, "aaa");
  };
}
class Name {
  fun(@Liu(100) a: string) {
    console.log(a); // 123
  }
}

// 输出
// 100
// {} fun 0 aaa

装饰器类型

  • ClassDecorator 是类装饰器,用于装饰类。
  • PropertyDecorator 是属性装饰器,用于装饰类的属性。
  • MethodDecorator 是方法装饰器,用于装饰类的方法。
  • ParameterDecorator 是参数装饰器,用于装饰类方法的参数。

装饰器执行顺序

  • 首先执行实例相关:参数装饰器 > 方法装饰器 > 类装饰器 > 属性装饰器
  • 然后执行静态相关:参数装饰器 > 方法装饰器 > 类装饰器 > 属性装饰器
  • 多个装饰器装饰同一个数据时,从下往上依次执行
  • 结果从上往下应用(函数返回的最终结果)。
function DecoratorA() {
    console.log("DecoratorA evaluated");
    return function (target: any) {
        console.log("DecoratorA executed");
    };
}

function DecoratorB() {
    console.log("DecoratorB evaluated");
    return function (target: any) {
        console.log("DecoratorB executed");
    };
}

@DecoratorA()
@DecoratorB()
class Example {}

// 输出

// DecoratorA evaluated
// DecoratorB evaluated
// DecoratorB executed
// DecoratorA executed