TypeScript 装饰器类型详解
一、类装饰器
function ClassDecorator(constructor: Function) {
Object.defineProperty(constructor.prototype, 'timestamp', {
value: Date.now()
});
}
@ClassDecorator
class DataService {
}
function Mixin(...mixins: any[]) {
return (constructor: Function) => {
Object.assign(constructor.prototype, ...mixins);
};
}
二、方法装饰器
function ValidateParams(validationRules: any[]) {
return (target: any, methodName: string, descriptor: PropertyDescriptor) => {
const original = descriptor.value;
descriptor.value = function (...args: any[]) {
args.forEach((arg, index) => {
if (!validationRules[index](arg)) {
throw new Error(`参数${index}验证失败`);
}
});
return original.apply(this, args);
};
};
}
class UserController {
@ValidateParams([
(name: string) => name.length > 3,
(age: number) => age >= 18
])
createUser(name: string, age: number) {
}
}
三、属性装饰器
function Observable(target: any, propertyName: string) {
let value = target[propertyName];
Object.defineProperty(target, propertyName, {
get: () => value,
set: (newVal) => {
console.log(`属性【${propertyName}】从${value}变为${newVal}`);
value = newVal;
}
});
}
class Stock {
@Observable
price: number = 100;
}
四、参数装饰器
function PathParam(paramName: string) {
return (target: any, methodName: string | symbol, parameterIndex: number) => {
const metadata = Reflect.getMetadata('params', target, methodName) || [];
metadata.push({ paramName, parameterIndex });
Reflect.defineMetadata('params', metadata, target, methodName);
};
}
class ApiController {
getUser(
@PathParam('userId') id: string,
@PathParam('type') category: string
) {
}
}
五、访问器装饰器
function Configurable(enabled: boolean) {
return (target: any, propertyName: string, descriptor: PropertyDescriptor) => {
descriptor.configurable = enabled;
};
}
class Settings {
private _theme = 'light';
@Configurable(false)
get theme() {
return this._theme;
}
}
参数对照表
装饰器类型 | 接收参数 | 典型应用场景 |
---|
类装饰器 | constructor: Function | 元数据注入、混入功能 |
方法装饰器 | target, methodName, descriptor | 方法增强、验证、日志 |
属性装饰器 | target, propertyName | 属性监听、格式校验 |
参数装饰器 | target, methodName, parameterIndex | 依赖注入、参数装饰 |
访问器装饰器 | target, propertyName, descriptor | 控制getter/setter行为 |
组合使用示例
@Injectable()
class PaymentService {
@ValidateCurrency
private _amount: number;
constructor(@Inject('API_KEY') apiKey: string) {}
@Throttle(1000)
async pay(@LogParam('amount') amount: number) {
}
}