前往小程序,Get更优阅读体验!
立即前往
腾讯云
开发者社区
文档 建议反馈 控制台
首页
学习
活动
专区
工具
TVP
最新优惠活动
发布
首页
学习
活动
专区
工具
TVP 最新优惠活动
返回腾讯云官网
社区首页 > 专栏 >ts装饰器(注解)

ts装饰器(注解)

作者头像
阿超
发布2022-08-21 14:07:57
1.2K0
发布2022-08-21 14:07:57
举报
文章被收录于专栏: 快乐阿超 快乐阿超

官方文档: https://www.tslang.cn/docs/handbook/decorators.html

这个东西在java里叫注解,不过在ts中,一个装饰器对应一个方法

首先执行命令:

代码语言:javascript
复制
tsc --target ES5 --experimentalDecorators

然后配置一下tsconfig.json就可以使用了

代码语言:javascript
复制
{
    "compilerOptions": {
        "target": "ES5",
        "experimentalDecorators": true
    }
}

首先我们定义一个class

代码语言:javascript
复制
class User {
  private id: Number | undefined;
  private name: string | undefined;
}

我们编写一个装饰器对应的逻辑,实现javalombok@Data生成gettersetter

代码语言:javascript
复制
function Data(constructor: Function | ObjectConstructor) {
  console.log('@Data', { constructor })
  Object.getOwnPropertyNames(new constructor()).forEach(key => {
    const firstUpperProperty = key.charAt(0).toUpperCase() + key.substring(1)
    if (!constructor.prototype[`get${firstUpperProperty}`]) {
      constructor.prototype[`get${firstUpperProperty}`] = function () {
        return this[key]
      }
    }
    if (!constructor.prototype[`set${firstUpperProperty}`]) {
      constructor.prototype[`set${firstUpperProperty}`] = function (value: any) {
        this[key] = value
      }
    }
  })
}

我们将这个注解放到类的上面

代码语言:javascript
复制
@Data
class User {
  private id: Number | undefined;
  private name: string | undefined;
}

尝试调用一下

代码语言:javascript
复制
const user = new User()
user.setId(1);
user.setName("John");
console.log(user.getId());			// 1
console.log(user.getName());		// "John"

可以看到确实生效,这里打印的参数:

image-20220621184302118
image-20220621184302118

顺带一提注解可以以复数形式存在,上方文档提到了,这里就不多赘述

我们继续编写注解,刚刚这个是类装饰器

接下来来个给默认的getter方法获取时,如果没有就提供一个默认值的注解@DefaultVal

这是一个属性装饰器

代码语言:javascript
复制
function DefaultVal(val: any) {
  return function (target: any, key: string) {
    console.log('@DefaultVal', { target, key, val });
    const firstUpperProperty = key.charAt(0).toUpperCase() + key.substring(1)
    target.constructor.prototype[`get${firstUpperProperty}`] = function () {
      return this[key] ?? val
    }
  };
}

注意优先级,我们的属性装饰器优先级高于我们的类装饰器,所以getter别被覆盖了

类中不同声明上的装饰器将按以下规定的顺序应用:

  1. 参数装饰器,然后依次是方法装饰器访问符装饰器,或属性装饰器应用到每个实例成员。
  2. 参数装饰器,然后依次是方法装饰器访问符装饰器,或属性装饰器应用到每个静态成员。
  3. 参数装饰器应用到构造函数。
  4. 类装饰器应用到类。

使用方式:

代码语言:javascript
复制
@Data
class User {
  private id: Number | undefined;
  @DefaultVal('nobody')
  private name: string | undefined;
}

演示:

代码语言:javascript
复制
console.log({ 'new User().getName()': new User().getName() });

输出结果:

代码语言:javascript
复制
{'new User().getName()': 'nobody'}

打印参数:

image-20220621184325477
image-20220621184325477

然后是方法装饰器

这里我们指定返回值不能为null,否则报错

代码语言:javascript
复制
function NonNull() {
  return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    console.log('@NonNull', { target, propertyKey, descriptor });
    let value = descriptor.value
    descriptor.value = () => {
      const result = value.call()
      if (result === null || result === undefined) throw new Error(`${propertyKey} must non-null`)
      return result
    }
  };
}

使用:

代码语言:javascript
复制
@Data
class User {
  private id: Number | undefined;
  @DefaultVal('nobody')
  private name: string | undefined;
  @NonNull()
  toString() {
    // return Object.prototype.toString();
    return null
  }
}

测试:

代码语言:javascript
复制
new User().toString();
image-20220621184052422
image-20220621184052422

打印结果:

image-20220621184340137
image-20220621184340137

最后是参数装饰器

这里懒得写了,就输出下日志吧:

代码语言:javascript
复制
function Log(target: Object, propertyKey: string | symbol, parameterIndex: number) {
  console.log('@Log', { target, propertyKey, parameterIndex });
}

使用:

代码语言:javascript
复制
@Data
class User {
  private id: Number | undefined;
  @DefaultVal('nobody')
  private name: string | undefined;
  @NonNull()
  toString() {
    return Object.prototype.toString();
    // return null
  }
  equals(@Log val: User) {
    return deepEqual(this, val);
  }
}

打印:

image-20220621184455024
image-20220621184455024
本文参与  腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-06-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与  腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
LV.
文章
0
获赞
0
领券
问题归档 专栏文章 快讯文章归档 关键词归档 开发者手册归档 开发者手册 Section 归档

装修网办公室装修费可以抵扣进项税吗简装改精装麻烦吗爱家装装修公司公装室内设计公司青岛简装多少钱大连装修公司十强哪家好130平米装修多少钱预算装修如何防治白蚁九江装饰三室两厅简装需多少钱简装香水是真的吗室内简装公司楼房简装大约多少钱春节装饰氛围精装修最低多少钱仙桃易和装饰公司欧式风格装修装修室内装修 简装卖衣服装修效果图简装马鞍山装饰装潢济南美巢装饰房屋简装一个月能完成吗常德市名匠装饰公司怎么样一百多平的民房简装一下多少钱144平米装修费用贵阳装修公司靠谱的90平米装修费用明细嘉兴无尘车间装修好装修装饰公司卤菜店装修香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声汪小菲曝离婚始末卫健委通报少年有偿捐血浆16次猝死单亲妈妈陷入热恋 14岁儿子报警雅江山火三名扑火人员牺牲系谣言手机成瘾是影响睡眠质量重要因素男子被猫抓伤后确诊“猫抓病”中国拥有亿元资产的家庭达13.3万户高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了男孩8年未见母亲被告知被遗忘张家界的山上“长”满了韩国人?倪萍分享减重40斤方法许家印被限制高消费网友洛杉矶偶遇贾玲何赛飞追着代拍打小米汽车超级工厂正式揭幕男子被流浪猫绊倒 投喂者赔24万沉迷短剧的人就像掉进了杀猪盘特朗普无法缴纳4.54亿美元罚金周杰伦一审败诉网易杨倩无缘巴黎奥运专访95后高颜值猪保姆德国打算提及普京时仅用姓名西双版纳热带植物园回应蜉蝣大爆发七年后宇文玥被薅头发捞上岸房客欠租失踪 房东直发愁“重生之我在北大当嫡校长”校方回应护栏损坏小学生课间坠楼当地回应沈阳致3死车祸车主疑毒驾事业单位女子向同事水杯投不明物质路边卖淀粉肠阿姨主动出示声明书黑马情侣提车了奥巴马现身唐宁街 黑色着装引猜测老人退休金被冒领16年 金额超20万张立群任西安交通大学校长王树国卸任西安交大校长 师生送别西藏招商引资投资者子女可当地高考胖东来员工每周单休无小长假兔狲“狲大娘”因病死亡外国人感慨凌晨的中国很安全恒大被罚41.75亿到底怎么缴考生莫言也上北大硕士复试名单了专家建议不必谈骨泥色变“开封王婆”爆火:促成四五十对测试车高速逃费 小米:已补缴天水麻辣烫把捣辣椒大爷累坏了

装修网 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化