前置知识: TypeScript

装饰器标准实现

00:00
1 min Advanced 2026/6/14

TypeScript Stage 3装饰器标准实现详解:类装饰器、方法装饰器与元数据。

1. Stage 3 装饰器概述

1.1 与旧版装饰器的区别

特性Legacy (experimental)Stage 3 (standard)
启用方式experimentalDecorators默认支持
API 风基于函数描述符基于上下文对象
类型安全
元数据需要 emitDecoratorMetadata内置 metadata

1.2 启用方式

{
  "compilerOptions": {
    // Stage 3 装饰器无需额外配置
    // 旧版需要:
    // "experimentalDecorators": true
  }
}

2. 类装饰器

function logged<T extends { new (...args: any[]): {} }>(value: T, context: ClassDecoratorContext) {
  const name = context.name;
  return class extends value {
    constructor(...args: any[]) {
      console.log(`Creating ${String(name)} with args:`, args);
      super(...args);
    }
  };
}

@logged
class User {
  constructor(public name: string) {}
}

new User('Alice'); // Creating User with args: ['Alice']

3. 方法装饰器

function debounce(delay: number) {
  return function (value: Function, context: ClassMethodDecoratorContext) {
    let timer: ReturnType<typeof setTimeout>;
    return function (this: any, ...args: any[]) {
      clearTimeout(timer);
      timer = setTimeout(() => value.call(this, ...args), delay);
    };
  };
}

class Search {
  @debounce(300)
  handleInput(query: string) {
    console.log('Searching:', query);
  }
}

4. 属性装饰器

function required(value: undefined, context: ClassFieldDecoratorContext) {
  return function (this: any, initialValue: any) {
    if (initialValue === undefined || initialValue === null) {
      throw new Error(`${String(context.name)} is required`);
    }
    return initialValue;
  };
}

class User {
  @required
  name: string;

  constructor(name: string) {
    this.name = name;
  }
}

5. 元数据

function route(path: string) {
  return function (value: Function, context: ClassMethodDecoratorContext) {
    context.metadata.routes ??= {};
    context.metadata.routes[context.name] = path;
  };
}

class ApiController {
  @route('/users')
  getUsers() {}

  @route('/users/:id')
  getUser() {}
}

6. 装饰器组合

// 多个装饰器从下到上执行(类似函数组合)
@log
@validate
@memoize
class Calculator {
  @debounce(100)
  @throttle(50)
  calculate() {}
}

知识检测

学习进度

-- 已学文档
--% 知识覆盖率

学习推荐

专注模式