装饰器是 TypeScript 的一项实验性功能,提供了一种声明式的方式来修改类和类成员。装饰器基于 ES7 提案,在 Angular、NestJS 等框架中广泛使用。
装饰器本质上是一个函数,在编译时被调用。装饰器接收不同的参数,取决于装饰的目标类型。
function myDecorator(target: any) {
console.log("装饰器被调用")
}
@myDecorator
class MyClass {}
装饰器在类定义时立即执行,而不是在实例化时。
使用装饰器需要在 tsconfig.json 中启用实验性功能。
{
"compilerOptions": {
"target": "ES5",
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}
experimentalDecorators 启用装饰器语法,emitDecoratorMetadata 启用装饰器元数据。
TypeScript 装饰器分为以下几类:
| 装饰器类型 | 应用目标 | 参数 |
|---|---|---|
| 类装饰器 | 类 | 构造函数 |
| 方法装饰器 | 方法 | target, propertyKey, descriptor |
| 属性装饰器 | 属性 | target, propertyKey |
| 参数装饰器 | 参数 | target, propertyKey, parameterIndex |
| 访问器装饰器 | getter/setter | target, propertyKey, descriptor |
装饰器工厂是一个返回装饰器的函数,可以接收参数。
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)
}
return descriptor
}
}
class Calculator {
@log("计算器")
add(a: number, b: number): number {
return a + b
}
}
const calc = new Calculator()
calc.add(1, 2)
多个装饰器可以同时应用于一个声明。
function first() {
console.log("first(): 工厂")
return function (target: any) {
console.log("first(): 装饰器")
}
}
function second() {
console.log("second(): 工厂")
return function (target: any) {
console.log("second(): 装饰器")
}
}
@first()
@second()
class MyClass {}
执行顺序:工厂函数从上到下,装饰器从下到上。
装饰器常用于以下场景:
一个简单的日志装饰器。
function log(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const original = descriptor.value
descriptor.value = function (...args: any[]) {
console.log(`调用 ${propertyKey}`)
console.log(`参数: ${JSON.stringify(args)}`)
const result = original.apply(this, args)
console.log(`返回: ${JSON.stringify(result)}`)
return result
}
return descriptor
}
class MathService {
@log
add(a: number, b: number): number {
return a + b
}
@log
multiply(a: number, b: number): number {
return a * b
}
}
const service = new MathService()
service.add(1, 2)
service.multiply(3, 4)
装饰器是一种声明式的方式,用于修改类和类成员的行为。装饰器本质上是一个函数,在编译时被调用。装饰器分为类装饰器、方法装饰器、属性装饰器、参数装饰器和访问器装饰器。装饰器工厂可以接收参数并返回装饰器。装饰器常用于日志、缓存、验证、权限控制等场景。