一文讲清TypeScript装饰器的概念以及如何使用TypeScript装饰器
TypeScript 装饰器是什么?
装饰器(Decorator)是TypeScript提供的一个高级语法,它类似于一种特殊类型的声明,可以附加到类声明,方法,访问符,属性或参数上。装饰器主要以函数的形式出现,运行在编译阶段,以实现对所修饰对象的行为的修改或增强。这是一个功能强大且在TypeScript编程中常用的特性。
TypeScript 装饰器有什么作用?
装饰器在 TypeScript 中的主要应用场景包括:
- 类装饰器: 可以观察、修改、或替换类定义。它在提供元编程能力方面特别有用,能够实现诸如依赖注入等高级概念。
- 方法装饰器: 可以监视、修改或者替换类的方法定义。这对于日志记录、性能监控、以及某些应用程序级别的业务逻辑(如记录操作者信息)有巨大的用处。
- 属性装饰器: 可以监视、修改或替换类的属性定义。比如实现类型检查,或者实现相关get/set方法等。
- 参数装饰器: 对类方法中的参数进行注解。
- 访问器装饰器: 用于装饰类的访问器,即类中的get与set方法。
如何使用 TypeScript 装饰器
装饰器的使用顺序是从外到内、由下至上。如果一个装饰器既可以应用到类上,也可以应用到类的方法、属性或参数上,那么对于这样的装饰器,它将首先应用到类上,然后是方法,接着是属性,最后是参数。
类装饰器的使用
通过定义一个包含正确签名的函数,你就能创建一个类装饰器。类装饰器的参数是构造函数。
typescript// 定义装饰器 function LogClass(target: Function) { console.log(`New instance of ${target.name} class created.`); } // 使用装饰器修饰类 @LogClass class MyClass { constructor() { console.log("This is MyClass constructor"); } }
在上述代码中,**@LogClass
便是一个装饰器,它在 MyClass
**类被实例化的时候会执行,此时控制台会打印出相关日志。
方法装饰器的使用
方法装饰器用于监视、修改或替换类方法的定义。
typescript// 定义装饰器 function LogMethod(target: any, propertyKey: string, descriptor: PropertyDescriptor) { console.log(`Method ${propertyKey} of class ${target.constructor.name} is called.`); } class MyClass { // 使用装饰器修饰方法 @LogMethod myMethod() { console.log("This is myMethod"); } }
方法装饰器**@LogMethod 的参数包括:目标类原型、方法名、以及描述符。在上述代码中,每次
**myMethod`方法被调用的时候,都会打印出相关日志。
属性装饰器的使用
在Typescript中,属性装饰器可以接收两个参数:
- 目标类的原型(对于静态成员则为类的构造函数),
- 该属性的名称。
我们可以根据自己的需要来定制属性装饰器。来看以下例子:
typescriptfunction logProperty(target: Object, key: string | symbol): any { let value = target[key]; // 属性值的 getter const getter = function() { console.log(`Get: ${key} => ${value}`); return value; }; // 属性值的 setter const setter = function(newVal: any) { console.log(`Set: ${key} => ${newVal}`); value = newVal; }; // 删除原始属性,替换为 getter 和 setter if (delete target[key]) { Object.defineProperty(target, key, { get: getter, set: setter, enumerable: true, configurable: true }); } } class MyClass { @logProperty public myProp: string; }
在这段代码中,我们设计了一个属性装饰器 @logProperty
,这个装饰器对于修饰的属性进行了监视,任何对属性的取值和赋值都将被打印出来。
参数装饰器的使用
参数装饰器是表示对类的构造函数,或者方法的参数进行装饰。参数装饰器会在运行时被调用,传入以下三个参数:
- 对于静态成员,是类的构造函数,对于实例成员,是类的原型对象。
- 成员的名字。(若装饰构造函数则为
undefined
) - 参数在函数参数列表中的索引。
请看以下示例:
typescriptfunction logParameter(target: Object, key: string | symbol, index: number) { console.log(`The decorator is applied to parameter: ${index} of method: ${key.toString()}`); } class MyClass { myMethod(@logParameter name: string) { return name; } }
在上述代码中,@logParameter
就是一个参数装饰器,它会在参数被使用时被调用并打印参数的索引和所在方法名。
访问器装饰器的使用
访问器是类的一个特性,主要分为get访问器和set访问器。在Typescript中,我们可以使用装饰器去装饰访问器。访问器装饰器和方法装饰器使用方式类似,仍然是分别接收目标类、访问器名、和描述符三个参数。
typescriptfunction logAccessor(target: Object, key: string | symbol, descriptor: TypedPropertyDescriptor<any>) { const originalGet = descriptor.get; descriptor.get = function() { console.log(`Get: ${key.toString()} => ${originalGet.call(this)}`); return originalGet.call(this); }; } class MyClass { private _name: string; @logAccessor get name(): string { return this._name; } set name(name: string) { this._name = name; } }
在这段代码中,@logAccessor
就是一个访问器装饰器,除了原有的功能之外,还会在每次取值的时候打印出name的值。
TypeScript 项目开启装饰器
在 tsconfig.json
文件中,有一个叫 experimentalDecorators
的属性,你需要将其设置为 true
,才能在 TypeScript 中启用装饰器。
json{ "compilerOptions": { "target": "es5", "experimentalDecorators": true, "emitDecoratorMetadata": true } }
在这个示例中:
"target": "es5"
表示输出的 JavaScript 代码符合 ES5 标准。"experimentalDecorators": true
表示启用装饰器。"emitDecoratorMetadata": true
表示额外生成装饰器的元数据,在某些情况下使用装饰器时,这是必须的。
总结
装饰器在 TypeScript 中的应用场景非常广泛,可以为我们提供强大的编程工具,如类装饰器、方法装饰器、属性装饰器、参数装饰器和访问器装饰器等,使得我们可以在编译阶段进行诸如日志记录、性能计算、参数验证等多种复杂的操作,使用这些装饰器,我们可以保持代码的整洁和解耦,使程序更易于理解和维护。