当前位置: 首页 > news >正文

TypeScript 装饰器类型详解

TypeScript 装饰器类型详解

一、类装饰器

// 参数:类的构造函数
function ClassDecorator(constructor: Function) {
  Object.defineProperty(constructor.prototype, 'timestamp', {
    value: Date.now()
  });
}

@ClassDecorator
class DataService {
  // 装饰后自动添加timestamp属性
}

// 混入示例
function Mixin(...mixins: any[]) {
  return (constructor: Function) => {
    Object.assign(constructor.prototype, ...mixins);
  };
}

二、方法装饰器

// 参数:target | methodName | descriptor
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) {
    // 创建用户逻辑
  }
}

三、属性装饰器

// 参数:target | propertyName
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;
}

四、参数装饰器

// 参数:target | methodName | parameterIndex
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
  ) {
    // 参数自动绑定路径参数
  }
}

五、访问器装饰器

// 参数:target | propertyName | descriptor
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) {
    // 支付逻辑
  }
}

相关文章:

  • Vulkan进阶系列1 - Vulkan应用程序结构(完整代码)
  • 使用PyTorch实现ResNet:从残差块到完整模型训练
  • Java项目之基于ssm的酒店客房管理系统(源码+文档)
  • AI 数字短视频数字人源码开发:开启虚拟内容创作新纪元​
  • 【UE5 C++课程系列笔记】33——商业化Json读写
  • 【2025年最新!软考中级】软件设计师考证知识点总结,串讲及真题合集
  • DeepSeek与ChatGPT的优势对比:选择合适的工具来提升工作效率
  • 为什么函数对象作为函数参数时,一般使用值类型形式?-番外篇
  • 企业数据危机频发,该如何提前预防数据泄露发生?
  • Java 集合 Map Stream流
  • [Linux]从零开始的vs code交叉调试arm Linux程序教程
  • 蛋白设计 ProteinMPNN
  • 【Json-Rpc #3】项目设计
  • OpenCV 图形API(16)将极坐标(magnitude 和 angle)转换为笛卡尔坐标(x 和 y)函数polarToCart()
  • XT-912在热交换站的应用
  • 8.6考研408内部排序算法比较与应用知识点深度解析
  • BEV感知中如何使用相机内外参?
  • 深度学习训练camp-第R7周:糖尿病预测模型优化探索
  • Flutter PopupMenuButton 深度解析:从入门到架构级实战
  • PyTorch数据加载流程解析