TypeScript 装饰器

执行顺序

  1. 属性装饰器
  2. 方法装饰器
  3. 方法参数装饰器
  4. 类装饰器

如果同一个类型的装饰器有多个,总是先执行后面的装饰器。

less 复制代码
class NestedClass {
  @IsString()
  @exceedLength()
  name: string;

  constructor(props: any) {
    this.name = props.name;
  }
}

先执行exceedLength()再执行IsString()

类装饰器

可以为构造函数新增或修改变量或方法

typescript 复制代码
@reportableClassDecorator
class BugReport {
  constructor(t: string) {
    this.title = t;
    this._type = 'report';
  }
}


// 类装饰器
function reportableClassDecorator<T extends { new (...args: any[]): {}}>(constructor: T) {
  return class extends constructor {
    reportingURL = "http://www...";
    sayHello = () => {
        console.log('hello everyone');
    }
  }
}

interface BugReportV2 extends BugReport {
  reportingURL: string
  sayHello: () => void
}

const report = new BugReport("shanghai") as BugReportV2;

console.log(report.name);   // "http://www..." 
report.sayHello();					// "hello everyone"

属性装饰器

可以用于收集属性信息,也可以用来给类添加额外的方法和属性

通过元数据修改

更便捷的获取格式化数据

typescript 复制代码
import "reflect-metadata";
const formatMetadataKey = Symbol("format");

class BugReport {
  _type: string;
  title: string;
  @format("My name is %s")
  name: string = 'shenxin';

  constructor(t: string) {
    this.title = t;
    this._type = 'report';
  }

  introduceMyself() {
    const _tmpName = getFormat(this, 'name');
    return _tmpName.replace("%s", this.name);
  }
}

function format(formatString: string) {
  return Reflect.metadata(formatMetadataKey, formatString);
}
function getFormat(target: any, propertyKey: string) {
  return Reflect.getMetadata(formatMetadataKey, target, propertyKey);
}

interface BugReportV2 extends BugReport {
  reportingURL: string
  sayHello: () => void
}

const report = new BugReport("shanghai") as BugReportV2;

report.type = 'test';
report.name = "wangya";

console.log('name::: ', report.introduceMyself());  // "My name is wangya"

通过访问器修改

限制数据类型

typescript 复制代码
class NestedClass {
  @IsString()
  name: string;

  constructor(props: any) {
    this.name = props.name;
  }
}

function IsString() {
  return function (target: any, key: string) {
    let _key: string;
    Object.defineProperty(target, key, {
      get: () => _key,
      set: value => {
        if (typeof value !== 'string') {
          throw(`${key} must be a string`)
        }
        _key = value;
      }
    });
  }
}

const person = new NestedClass({
  name: 28,
});

console.log('person: ', person.name); // [ERR]: "name must be a string" 

方法装饰器

typescript 复制代码
class BugReport {
  _type: string;
  title: string;
  
  name: string = 'shenxin';

  constructor(t: string) {
    this.title = t;
    this._type = 'report';
  }
  
  @addHello
  getTitle() {
    return this.title;
  }
}


// 方法装饰器
function addHello(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    const _getTitle = descriptor.value;
    
    descriptor.value = function() {
      return `hello ${_getTitle.bind(this)()}`;
    }
}


const report = new BugReport("shanghai");

console.log(report.getTitle());     // "hello shanghai"

访问器装饰器

typescript 复制代码
class BugReport {
  _type: string;
  title: string;
  name: string = 'shenxin';

  constructor(t: string) {
    this.title = t;
    this._type = 'report';
  }
  

  @addTmp
  set type(value: string) {
    this._type = value;
  }
  get type() {
    return this._type;
  }
}

// 访问器装饰器
function addTmp(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
  const originSet = descriptor.set || function(){};

  descriptor.set = function(value: string) {
    // 获取方法参数
    return originSet.call(this, `this is ${value}`);
  }
}

const report = new BugReport("shanghai");

report.type = 'test';
console.log('report.type::: ', report.type);  // "this is test" 
相关推荐
东风破_3 小时前
danci 项目(三):从 JSON 数据到 AI Coding,真实项目里的数据清洗、Prompt 和工程规范
前端·后端·node.js
东风破_3 小时前
danci 项目(一):从需求到架构,一个单词学习系统为什么会这样设计
前端·后端·node.js
蒲公英eric4 小时前
从客户端到服务端:DVWA DOM 型 XSS 模块完整漏洞分析教程
前端·web安全·ai·xss·dvwa·ai安全
单线程_014 小时前
从案例分析 Vue3 Tokenizer+Parser 源码三
前端·javascript·vue.js
顶点多余4 小时前
那些在算法中适合巩固的知识点---1
java·前端·算法
Setsuna_F_Seiei5 小时前
前端转型 Agent 开发 03 之 Agent Tools - 给 Agent 装上手脚
前端·agent·ai编程
jay神5 小时前
【计算机毕业设计】基于SpringBoot的程序教学辅助系统
java·前端·vue.js·spring boot·后端·毕业设计·课程设计
kyriewen7 小时前
我装了30多个Skill,给AI安排了8个岗位
前端·javascript·ai编程
风骏时光牛马8 小时前
大模型落地实践中的技术选型思路与方案对比
前端
IT_陈寒8 小时前
Vite打包时的静态资源坑,我帮你踩过了
前端·人工智能·后端