TypeScript装饰器

约2分钟

装饰器是一种特殊类型的声明,它能够被附加到类声明方法访问符属性参数上。 装饰器使用 @expression这种形式,expression求值后必须为一个函数,它会在运行时被调用,被装饰的声明信息做为参数传入。

装饰器类型

首先要明确地是,TS中的装饰器实现本质是一个语法糖,它的本质是一个函数,如果调用形式为@deco(),那么这个函数应该再返回一个函数来实现调用。

declare type ClassDecorator = <TFunction extends Function>(
	target: TFunction
) => TFunction | void

declare type PropertyDecorator = (
	target: Object,
	propertyKey: string | symbol
) => void

declare type MethodDecorator = <T>(
	target: Object,
	propertyKey: string | symbol,
	descriptor: TypedPropertyDescriptor<T>
) => TypedPropertyDescriptor<T> | void

declare type ParameterDecorator = (
	target: Object,
	propertyKey: string | symbol | undefined,
	parameterIndex: number
) => void

例如,如下代码

// 装饰器函数
function Sealed(constructor: Function) {
  Object.seal(constructor);
}
// 装饰器工厂函数
function InjectUser():ClassDecorator {
  return function (constructor) {
    constructor.prototype.user = "user";
  }
}
const checkSymbol = Symbol("check");
// 元数据 属性装饰器
function CheckKey(
):PropertyDecorator{
  return (target, key) => {
   const existKey = Reflect.getMetadata(checkSymbol, target.constructor) ?? []
   existKey.push(key);
   Reflect.defineMetadata(checkSymbol, existKey, target.constructor)
  }
}
//方法装饰器
function CheckMethod(): MethodDecorator {
  return (target, key, descriptor) => {
    console.log(`CheckMethod ${key}`);
  }
}
// 参数装饰器

function User(): ParameterDecorator {
  return (target, key, index) => {
    console.log(target, key, index);
    return `${index}`
  }
}

@Sealed
@InjectUser()
class Greeter {
  @CheckKey()
  greeting!: string;
  @CheckKey()
  otherKey!: string;
  @CheckMethod()
  findPage(@User() user: string) {
    console.log(user);
  }
}
const greeter =new Greeter();
console.log((greeter as any).user);
console.log( Reflect.getMetadata(checkSymbol, Greeter))
建议更改

上次更新于: 2025-12-25 07:43