TypeScript 装饰器基础指南

56 阅读1分钟

TypeScript 装饰器基础指南

目录

  1. 基本语法
  2. 装饰器类型
  3. 装饰器工厂
  4. 返回值处理
  5. 应用示例

基本语法

启用装饰器

// tsconfig.json
{
  "compilerOptions": {
    "target": "ES5",
    "experimentalDecorators": true
  }
}

基本结构

// 简单装饰器
function simpleDecorator(target: any) {
  // 装饰器逻辑
}

@simpleDecorator
class Example {
  // 类的内容
}

装饰器类型

1. 类装饰器

function Logger(constructor: Function) {
  console.log('Class decorated:', constructor.name);
}

@Logger
class Person {
  name = 'Max';
}

2. 方法装饰器

function Log(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
  const original = descriptor.value;
  descriptor.value = function(...args: any[]) {
    console.log(`Calling ${propertyKey} with:`, args);
    return original.apply(this, args);
  };
}

class Calculator {
  @Log
  add(a: number, b: number) {
    return a + b;
  }
}

3. 属性装饰器

function ReadOnly(target: any, propertyKey: string) {
  Object.defineProperty(target, propertyKey, {
    writable: false
  });
}

class User {
  @ReadOnly
  name: string = "John";
}

装饰器工厂

装饰器工厂是返回装饰器的函数,允许自定义装饰器行为。

function Logger(prefix: string) {
  return function(target: any) {
    console.log(`${prefix}: ${target.name}`);
  };
}

@Logger('LOGGING')
class Person {
  name = 'Max';
}

返回值处理

1. 类装饰器返回值

function WithTemplate(template: string) {
  return function<T extends { new(...args: any[]): {} }>(target: T) {
    // 返回新的构造函数
    return class extends target {
      constructor(...args: any[]) {
        super(...args);
        console.log(template);
      }
    };
  };
}

@WithTemplate('<h1>My Person Object</h1>')
class Person {
  name = 'Max';
}

2. 方法装饰器返回值

function Measure(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
  const originalMethod = descriptor.value;

  descriptor.value = function(...args: any[]) {
    const start = performance.now();
    const result = originalMethod.apply(this, args);
    const end = performance.now();
    console.log(`${propertyKey} took ${end - start}ms`);
    return result;
  };

  return descriptor;
}

应用示例

1. 验证装饰器

function Validate(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
  const originalMethod = descriptor.value;

  descriptor.value = function(price: number) {
    if (price <= 0) {
      throw new Error('Price must be positive');
    }
    return originalMethod.call(this, price);
  };
}

class Product {
  @Validate
  setPrice(price: number) {
    this._price = price;
  }
}

2. 替换类实现

function APIVersion(version: string) {
  return function<T extends { new(...args: any[]): {} }>(originalConstructor: T) {
    return class extends originalConstructor {
      constructor(...args: any[]) {
        super(...args);
        this.version = version;
      }

      getVersion() {
        return this.version;
      }
    };
  };
}

@APIVersion('1.0.0')
class API {
  // 原始类实现
}

const api = new API();
console.log(api.getVersion()); // 输出: 1.0.0

3. 属性转换

function UpperCase(target: any, propertyKey: string) {
  let value: string;
  
  Object.defineProperty(target, propertyKey, {
    get: () => value,
    set: (newValue: string) => {
      value = newValue.toUpperCase();
    }
  });
}

class User {
  @UpperCase
  name: string;
}

const user = new User();
user.name = 'john';
console.log(user.name); // 输出: JOHN