TypeScript--装饰器
前言
TypeScript 中的装饰器是一种特殊的语法,可以用来修改类、方法、属性或参数的行为。装饰器是一种函数,它接收一个目标对象或一个属性描述符作为参数,并可以返回一个新的对象或属性描述符,或者不返回任何值。装饰器可以用来实现一些常见的编程模式,例如依赖注入、日志、缓存、验证等。
使用
要使用装饰器,需要在 tsconfig.json 文件中设置 experimentalDecorators 选项为 true。装饰器的名称通常以@符号开头,例如@log 或@Injectable。装饰器可以应用在类、类的方法、类的属性或类的参数上,分别称为类装饰器、方法装饰器、属性装饰器或参数装饰器。不同类型的装饰器有不同的参数和返回值,具体如下:
类装饰器:接收一个类的构造函数作为唯一参数,可以返回一个新的构造函数或不返回任何值。类装饰器可以用来修改或替换类的定义,例如添加新的属性或方法,或改变类的继承关系。
1
2
3
4
5
6
7
8
9
10
11
12function addProperty(target: any) {
target.prototype.newProperty = "new property";
}
class MyClass {
oldProperty = "old property";
}
const myObject = new MyClass();
console.log(myObject.oldProperty); // 'old property'
console.log(myObject.newProperty); // 'new property'方法装饰器:接收三个参数,分别是目标类的原型对象,方法的名称,和方法的属性描述符。可以返回一个新的属性描述符或不返回任何值。方法装饰器可以用来修改或替换方法的定义,例如改变方法的可枚举性,或添加额外的逻辑。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21function log(target: any, key: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
console.log(`Calling ${key} with arguments: ${JSON.stringify(args)}`);
const result = originalMethod.apply(this, args);
console.log(`Result: ${JSON.stringify(result)}`);
return result;
};
return descriptor;
}
class MyClass {
myMethod(arg1: string, arg2: number) {
return `${arg1}-${arg2}`;
}
}
const myObject = new MyClass();
myObject.myMethod("hello", 42); // Calling myMethod with arguments: ["hello",42]
// Result: "hello-42"属性装饰器:接收两个参数,分别是目标类的原型对象和属性的名称。没有返回值。属性装饰器可以用来修改或替换属性的定义,例如改变属性的可配置性,或定义访问器函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30function log(target: any, key: string, descriptor: PropertyDescriptor) {
const originalGetter = descriptor.get;
descriptor.get = function () {
console.log(`Getting ${key}`);
const result = originalGetter.call(this);
console.log(`Result: ${JSON.stringify(result)}`);
return result;
};
return descriptor;
}
class MyClass {
private _myProperty: string = "";
get myProperty() {
return this._myProperty;
}
set myProperty(value: string) {
console.log(`Setting myProperty to ${value}`);
this._myProperty = value;
}
}
const myObject = new MyClass();
myObject.myProperty = "hello";
console.log(myObject.myProperty); // Getting myProperty
// Result: "hello"
// "hello"参数装饰器:接收三个参数,分别是目标类的原型对象,方法的名称,和参数在参数列表中的索引。没有返回值。参数装饰器可以用来注入依赖,或检查参数的类型。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24function uppercase(target: any, key: string) {
let value = target[key];
const getter = function () {
return value;
};
const setter = function (newVal: string) {
value = newVal.toUpperCase();
};
Object.defineProperty(target, key, {
get: getter,
set: setter,
enumerable: true,
configurable: true,
});
}
class MyClass {
myProperty: string = "";
}
const myObject = new MyClass();
myObject.myProperty = "hello";
console.log(myObject.myProperty); // 'HELLO'