装饰器介绍
TypeScript 中的装饰器可以分为类装饰器、方法装饰器、访问符装饰器、属性装饰器,最常见的主要还是类装饰器、方法装饰器以及属性装饰器。
类装饰器
function AddMethod() {
return (originalClass: any, context: DecoratorContext) => {
if (context.kind === "class") {
originalClass.prototype.newInstanceMethod = () => {
console.log("Let's add a new instance method!");
}
originalClass.newStaticMethod = () => {
console.log("Let's add a new static method!");
};
}
}
}
function AddProperty(value: string) {
return (originalClass: any, context: DecoratorContext) => {
if (context.kind === "class") {
originalClass.prototype.newInstanceProperty = value
originalClass.newStaticProperty = `static ${value}`
}
}
}
function OverrideFoo (originalClass: any, context: DecoratorContext) {
return class extends originalClass {
constructor(...args: any[]) {
super(...args)
}
printMessage() {
console.log("hello world")
}
}
}
@OverrideFoo
@AddProperty("hello")
@AddMethod()
class Foo {
}
const foo = new Foo();
(foo as any).newInstanceMethod();
(Foo as any).newStaticMethod();
console.log((foo as any).newInstanceProperty);
console.log((Foo as any).newStaticProperty);
(foo as any).printMessage()
方法装饰器
function LoggedMethod(originalMethod: any, context: ClassMethodDecoratorContext) {
const methodName = String(context.name);
const replaceMethod = function(this: any, ...args: any[]) {
console.log(`LOG: Entering method '${methodName}'.`);
const result = originalMethod.call(this, ...args);
console.log(`LOG: Exiting method '${methodName}'.`);
return result;
}
return replaceMethod;
}
function Bound(originalMethod: any, context: ClassMethodDecoratorContext) {
const methodName = context.name
if (context.private) {
throw new Error("'bound' cannot decorate private properties like ${methodName as string}.")
}
context.addInitializer(function() {
(this as any)[methodName] = (this as any)[methodName].bind(this);
})
}
class Person {
constructor(public name: string) {}
@LoggedMethod
@Bound
greet() {
console.log(`Hello, my name is ${this.name}`)
}
}
const person = new Person("John");
const greet = person.greet;
greet()
属性装饰器
function Prefix(_: any, context: ClassFieldDecoratorContext) {
if (context.kind === "field") {
return function(initialValue: any) {
return `hello, my Name is ${initialValue}`
}
}
}
class Person {
@Prefix
name = "yutt"
}
const person = new Person()
console.log(person.name)