Logo

TypeScript 5+装饰器写法:提升代码复用的利器

author
YGHub·2025-05-10·0·字数:1183 字·阅读时间:4 分钟

TypeScript 5+凭借其强大的类型系统和装饰器(Decorators)功能,成为2025年前端和Node.js开发的首选语言。

TypeScript 5+装饰器写法 让开发者通过元编程简化代码复用、增强类和方法功能,广泛应用于框架(如NestJS、Angular)和库设计。从日志记录到权限验证,装饰器提供优雅的解决方案。

什么是TypeScript 5+装饰器?

装饰器是一种实验性功能(TypeScript 5.0+稳定支持,遵循ECMAScript提案),通过@decorator语法为类、方法、属性或参数添加元数据或行为。

TypeScript 5+优化了装饰器性能,支持标准语法(无需experimentalDecorators),并增强了元数据反射。典型场景包括:

  • 代码复用:自动添加日志、验证或缓存。
  • 框架开发:如NestJS的@Controller、Angular的@Component
  • 调试与监控:记录方法执行时间或参数。

以下6种用法覆盖常见场景,基于TypeScript 5.5+标准语法。

用法1:类装饰器 - 添加全局元数据

为什么使用? 类装饰器为整个类添加行为或元数据,如日志或依赖注入,适合框架开发。

实现方法

  1. 定义类装饰器:
    typescript
    function LogClass<T extends { new (...args: any[]): {} }>(constructor: T) {
    return class extends constructor {
    constructor(...args: any[]) {
    super(...args);
    console.log(`Class ${constructor.name} instantiated`);
    }
    };
    }
     
  2. 使用装饰器:
    typescript
    @LogClass
    class User {
    name: string;
    constructor(name: string) {
    this.name = name;
    }
    }
     
  3. 测试代码:
    typescript
    const user = new User("Alice");
     
  4. 验证:控制台输出:
    Class User instantiated
     

注意:确保tsconfig.json启用emitDecoratorMetadataexperimentalDecorators(如需向后兼容)。

用法2:方法装饰器 - 日志记录

为什么使用? 方法装饰器拦截方法调用,添加日志或性能监控,适合调试。

实现方法

  1. 定义方法装饰器:
    typescript
    function LogMethod(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    const originalMethod = descriptor.value;
    descriptor.value = function (...args: any[]) {
    console.log(`Calling ${propertyKey} with args: ${args}`);
    return originalMethod.apply(this, args);
    };
    }
     
  2. 使用装饰器:
    typescript
    class Calculator {
    @LogMethod
    add(a: number, b: number) {
    return a + b;
    }
    }
     
  3. 测试代码:
    typescript
    const calc = new Calculator();
    calc.add(2, 3);
     
  4. 验证:控制台输出:
    Calling add with args: 2,3
     

注意:装饰器不会修改方法返回值,仅增强行为。

用法3:属性装饰器 - 数据验证

为什么使用? 属性装饰器为属性添加验证逻辑,如确保值非空,适合表单处理。

实现方法

  1. 定义属性装饰器:
    typescript
    function Required(target: any, propertyKey: string) {
    Object.defineProperty(target, propertyKey, {
    set(value) {
    if (value == null) throw new Error(`${propertyKey} is required`);
    this[`_${propertyKey}`] = value;
    },
    get() {
    return this[`_${propertyKey}`];
    },
    });
    }
     
  2. 使用装饰器:
    typescript
    class Profile {
    @Required
    username: string;
    constructor(username: string) {
    this.username = username;
    }
    }
     
  3. 测试代码:
    typescript
    const profile = new Profile("Bob");
    console.log(profile.username); // Bob
    profile.username = null; // 抛出错误
     
  4. 验证:设置null抛出username is required错误。

注意:需为属性添加私有存储(如_前缀)。

用法4:参数装饰器 - 注入元数据

为什么使用? 参数装饰器记录参数信息,适合依赖注入或验证,常见于框架。

实现方法

  1. 定义参数装饰器:
    typescript
    function LogParam(target: any, propertyKey: string, parameterIndex: number) {
    console.log(`Parameter ${parameterIndex} in ${propertyKey} decorated`);
    }
     
  2. 使用装饰器:
    typescript
    class Service {
    greet(@LogParam name: string) {
    return `Hello, ${name}`;
    }
    }
     
  3. 测试代码:
    typescript
    const service = new Service();
    service.greet("Charlie");
     
  4. 验证:控制台输出:
    Parameter 0 in greet decorated
     

注意:参数装饰器需结合反射库(如reflect-metadata)以扩展功能。

用法5:方法装饰器 - 性能监控

为什么使用? 记录方法执行时间,适合优化性能或调试复杂逻辑。

实现方法

  1. Define the performance decorator:
    typescript
    function MeasureTime(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    const originalMethod = descriptor.value;
    descriptor.value = async function (...args: any[]) {
    const start = performance.now();
    const result = await originalMethod.apply(this, args);
    const end = performance.now();
    console.log(`${propertyKey} took ${end - start}ms`);
    return result;
    };
    }
     
  2. 使用装饰器:
    typescript
    class Processor {
    @MeasureTime
    async compute(data: number[]) {
    return data.reduce((a, b) => a + b, 0);
    }
    }
     
  3. 测试代码:
    typescript
    const proc = new Processor();
    proc.compute([1, 2, 3, 4, 5]);
     
  4. 验证:控制台输出类似:
    compute took 0.123ms
     

注意:支持异步方法,需await确保准确计时。

用法6:组合装饰器 - 权限控制

为什么使用? 组合多个装饰器实现复杂逻辑,如权限检查和日志,适合企业应用。

实现方法

  1. 定义权限装饰器:
    typescript
    function Restrict(role: string) {
    return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    const originalMethod = descriptor.value;
    descriptor.value = function (...args: any[]) {
    if (args[0] !== role) throw new Error(`Requires ${role} role`);
    return originalMethod.apply(this, args);
    };
    };
    }
     
  2. 组合装饰器:
    typescript
    class AdminPanel {
    @LogMethod
    @Restrict("admin")
    manage(userRole: string) {
    return "Managing system";
    }
    }
     
  3. 测试代码:
    typescript
    const panel = new AdminPanel();
    panel.manage("admin"); // 成功
    panel.manage("user"); // 抛出错误
     
  4. 验证:控制台输出:
    Calling manage with args: admin
     
    非admin角色抛出Requires admin role错误。

注意:装饰器顺序重要,@LogMethod先执行。

优化建议

为高效使用TypeScript 5+装饰器写法

  1. 启用配置:在tsconfig.json中设置:
    json
    {
    "compilerOptions": {
    "target": "ES2022",
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
    }
    }
     
  2. 使用反射:安装reflect-metadata以增强元数据功能:
    bash
    npm install reflect-metadata
     
    main.ts中导入:
    typescript
    import 'reflect-metadata';
     
  3. 模块化装饰器:将装饰器提取到单独文件,提升复用性。
  4. 测试用例:为装饰器编写单元测试,确保逻辑正确:
    typescript
    import { expect } from 'chai';
    it('should log method call', () => {
    // 测试代码
    });
     
  5. 框架集成:在NestJS中使用@Injectable等内置装饰器,结合自定义装饰器。

TypeScript 5+装饰器写法 是提升代码复用和可维护性的强大工具。

从类装饰器添加元数据,到方法装饰器记录日志、属性装饰器验证数据、参数装饰器注入信息,再到性能监控和权限控制,这些用法让你的TypeScript项目更优雅。

Preview

点个赞 ~

版权申明: © 本文著作权归YGHub所有,未经YGHub网授权许可,禁止第三方以任何形式转载和使用本文内容。