在 TypeScript 中,装饰器(Decorators)是一种特殊类型的声明,可以附加到类声明、方法、访问器、属性或参数上,以修改其行为或添加元数据。TypeScript 支持多种装饰器,包括类装饰器、方法装饰器、属性装饰器、访问器装饰器和参数装饰器。
类装饰器(Class Decorators)
类装饰器在类声明之前声明,并用 @ 符号应用于类声明之前。类装饰器可以用来:
- 修改类的行为。
- 修改类的构造函数。
- 添加静态属性或方法。
例如,以下是一个简单的类装饰器示例:
function logged(constructorFn: Function) {
console.log(constructorFn);
}
@logged
class Person {
constructor() {
console.log("Hi there!");
}
}
在这个例子中,@logged 装饰器将 Person 类传递给 logged 函数,并输出构造函数 Person 的定义。
方法装饰器(Method Decorators)
方法装饰器应用于方法的声明之前,用来监视、修改或替换方法定义。它接收三个参数:目标对象、方法名和属性描述符。
function enumerable(value: boolean) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
descriptor.enumerable = value;
};
}
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
@enumerable(false)
greet() {
return "Hello, " + this.greeting;
}
}
在这个例子中,@enumerable(false) 装饰器使 greet 方法变为不可枚举的,即不会出现在对象的属性列表中。
访问器装饰器(Accessor Decorators)
访问器装饰器应用于访问器的声明之前,用来监视、修改或替换访问器的定义。
function configurable(value: boolean) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
descriptor.configurable = value;
};
}
class Point {
private _x: number = 0;
private _y: number = 0;
@configurable(false)
get x() { return this._x; }
@configurable(true)
get y() { return this._y; }
}
在这个例子中,@configurable(false) 和 @configurable(true) 装饰器分别用于 x 和 y 访问器,设置它们的 configurable 属性。
属性装饰器(Property Decorators)
属性装饰器应用于属性的声明之前,用来监视、修改或替换属性的定义。
function format(target: any, propertyKey: string) {
let value = target[propertyKey];
const getter = function () {
return value;
};
const setter = function (newVal: string) {
value = `[ ${newVal} ]`;
};
Object.defineProperty(target, propertyKey, {
get: getter,
set: setter,
enumerable: true,
configurable: true
});
}
class Greeter {
@format
message: string;
constructor(message: string) {
this.message = message;
}
}
const greeter = new Greeter("world");
console.log(greeter.message); // Output: [ world ]
在这个例子中,@format 装饰器修改了 message 属性的 getter 和 setter 方法,使其在获取和设置时自动添加括号。
参数装饰器(Parameter Decorators)
参数装饰器应用于函数参数的声明之前,用来监视、修改或替换参数的定义。
function logParameter(target: any, propertyName: string, index: number) {
const metadataKey = `log_${propertyName}_parameters`;
if (Array.isArray(target[metadataKey])) {
target[metadataKey].push(index);
} else {
target[metadataKey] = [index];
}
}
class Calculator {
add(@logParameter x: number, y: number): number {
return x + y;
}
}
const calc = new Calculator();
calc.add(1, 2); // Output: Logs [0] which indicates the index of the parameter decorated
在这个例子中,@logParameter 装饰器记录了 add 方法中第一个参数 x 的索引。
总结
TypeScript 的装饰器提供了一种强大的机制,可以以声明式的方式修改类和其成员的行为,或者添加额外的元数据。它们可以帮助开发者更加灵活和高效地组织和管理代码。然而,需要注意的是,装饰器目前仍处于实验性阶段,并可能在未来的 TypeScript 版本中发生变化。