TS-装饰器

本文详细介绍了TypeScript中的装饰器,包括类装饰器、方法装饰器、访问器装饰器、属性装饰器和参数装饰器。装饰器允许我们在不修改原有代码的基础上,增加新的功能或进行元数据标记,提高了代码的可扩展性和维护性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介

介绍:装饰器是一种特殊类型的声明,它能够被附加到类,方法, 访问器,属性或参数上。用 @添加
装饰器本质上还是一个函数,在别的语言中已广泛使用,如: python, 但在TS中依旧为一个测试中的版本,若要启 用实验性的装饰器特性,你必须在命令行或tsconfig.json里启用experimentalDecorators编译器选项

在这里插入图片描述

添加到类上, 类装饰器
添加到方法上,方法装饰器
添加到访问器上,访问器装饰器
添加到属性上,属性装饰器
添加到参数上,参数装饰器

装饰器工厂:如果我们要定制一个修饰器如何应用到一个声明上,我们得写一个装饰器工厂函数。 装饰器工厂就是一个简 单的函数,它返回一个表达式,以供装饰器在运行时调用

类的装饰器

  • 类装饰器就在类声明之前被声明
  • 类装饰器被应用于类的构造函数,可以用来观察、修改或替换类定义
  • 类装饰器不能用在声明文件中( .d.ts),也不能用在任何外部上下文中(比如declare的类)
  • 类装饰器表达式会在运行时当作函数被调用,类的构造函数作为其唯一的参数
  • 如果类装饰器返回一个值,它会使用提供的构造函数来替换类的声明。
function testDecorator(constructor: any) {
  constructor.prototype.uname = "张三";
  constructor.prototype.show = (): void => {
    console.log(`我是${constructor.prototype.uname}`);
  };
}
@testDecorator
class Person {}

let person = new Person();
// person.show(); 类型“Person”上不存在属性“show”
(person as any).show();
// 使用工厂函数
function testDecorator(flag: boolean) {
  if (flag) {
    return function (constructor: any) {
      constructor.prototype.uname = "张三";
      constructor.prototype.show = (): void => {
        console.log(`我是${constructor.prototype.uname}`);
      };
    };
  } else {
    return function (constructor: any) {};
  }
}

@testDecorator(true)
class Person {}

let person = new Person();
(person as any).show();

解决person as any 才能调用 show()的问题

// 函数可以接收很多的参数,参数类型都是any,将它们放在一个数组中
// T就相当于一个类,里面有构造函数
function testDecorator<T extends new (...args: any[]) => {}>(constructor: T) {
  // 直接constructor做扩展
  return class extends constructor {
    name = "张三";
    show() {
      console.log(`我是${this.name}`);
    }
  };
}

@testDecorator
class Person {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
}

let person = new Person("李四");
(person as any).show(); // 我是张三

// 工厂模式
function testDecorator() {
  return function <T extends new (...args: any[]) => {}>(constructor: T) {
    // 直接constructor做扩展
    return class extends constructor {
      name = "张三";
      show() {
        console.log(`我是${this.name}`);
      }
    };
  };
}
const Person = testDecorator()(
  class {
    name: string;
    constructor(name: string) {
      this.name = name;
    }
  }
);

let person = new Person("李四");
person.show(); // 我是张三

方法装饰器

  • 方法装饰器写在在一个方法的声明之前
  • 方法装饰器可以用来监视,修改或者替换方法定义。
  • 方法装饰器表达式会在运行时当作函数被调用,传入下列3个参数:
    静态成员的类的构造函数,或者实例成员的类的原型
    成员的名称
    该成员的属性描述符
function getNameDecorator(
  target: any,
  key: string,
  descriptor: PropertyDescriptor
) {
  console.log("target:", target); 
  console.log("key:", key);  
  console.log("descriptor:", descriptor); 
  /* 
    target: {}
    key: getName
    descriptor: {
    value: [Function: getName],
    writable: true,
    enumerable: false,
    configurable: true
  }
  */

}

class Person {
  name: string = "张三";
  constructor(name: string) {
    this.name = name;
  }
  @getNameDecorator
  getName() {
    return this.name;
  }
}
let person = new Person("李四");
console.log(person.getName());

访问器的装饰器

访问器装饰器声明在一个访问器的声明之前(紧靠着访问器声明)。 访问器装饰器应用于访问器的 属性描述符并且可以用来监视,修改或替换一个访问器的定义。 访问器装饰器不能用在声明文件中(.d.ts),或者任何外部上下文(比如 declare的类)里。

方法装饰器表达式会在运行时当作函数被调用,传入下列3个参数:

  1. 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
  2. 成员的名称。
  3. 该成员的属性描述符

TypeScript不允许同时装饰一个成员的get和set访问器。

function visitDecorator(
  target: any,
  key: string,
  descriptor: PropertyDescriptor
) {
  console.log(target);
}

class Test {
  private _name: string;

  constructor(name: string) {
    this._name = name;
  }
  get name() {
    return this._name;
  }
  set name(newName: string) {
    this._name = newName;
  }
}

const t = new Test("张三");

console.log(t.name);

属性的修饰器

  • 属性装饰器写在一个属性声明之前(紧靠着属性声明)
  • 属性装饰器表达式会在运行时当作函数被调用,传入下列2个参数:
    对于静态属性来说就是当前的类, 对于实例属性来说就是当前实例
    成员的名字
function nameDecorator(target: any, key: string): any {}

class Test {
  @nameDecorator
  name = "张三";
}

let test = new Test();
console.log(test.name);

参数装饰器

  • 参数装饰器声明在一个参数声明之前(紧靠着参数声明)
  • 参数装饰器应用于类构造函数或方法声明
  • 数装饰器不能用在声明文件(.d.ts),重载或其它外部上下文(比如 declare的类)里
  • 参数装饰器表达式会在运行时当作函数被调用,传入下列3个参数:
    对于静态成员来说是当前的类,对于实例成员是当前实例。
    参数所在的方法名称。
    参数在参数列表中的索引。
function paramDecorator(target: any, method: string, index: number) {
  console.log(target, method, index);
}

class Test {
  getInfo(name: string, @paramDecorator age: number) {
    console.log(name, age);
  }
}

const test = new Test();
test.getInfo("张三", 18);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值