当前位置:首页 > 科技  > 软件

TypeScript 装饰器实用指南!

来源: 责编: 时间:2023-08-09 23:03:20 386观看
导读一、装饰器的概念 Summer IS HERE在 TypeScript 中,装饰器就是可以添加到类及其成员的函数。TypeScript 装饰器可以注释和修改类声明、方法、属性和访问器。Decorator类型定义如下:type Decorator = (target: Input, co

fo028资讯网——每日最新资讯28at.com

一、装饰器的概念 Summer IS HERE

在 TypeScript 中,装饰器就是可以添加到类及其成员的函数。TypeScript 装饰器可以注释和修改类声明、方法、属性和访问器。Decorator类型定义如下:fo028资讯网——每日最新资讯28at.com

type Decorator = (target: Input, context: {  kind: string;  name: string | symbol;  access: {    get?(): unknown;    set?(value: unknown): void;  };  private?: boolean;  static?: boolean;  addInitializer?(initializer: () => void): void;}) => Output | void;

上面的类型定义解释如下:fo028资讯网——每日最新资讯28at.com

  • target:代表要装饰的元素,其类型为 Input。
  • context 包含有关如何声明修饰方法的元数据,即:
  • kind:装饰值的类型。正如我们将看到的,这可以是类、方法、getter、setter、字段或访问器。
  • name:被装饰对象的名称。
  • access:引用 getter 和 setter 方法来访问装饰对象的对象。
  • private:被装饰的对象是否是私有类成员。
  • static:被修饰的对象是否是静态类成员。
  • addInitializer:一种在构造函数开头(或定义类时)添加自定义初始化逻辑的方法。
  • Output:表示 Decorator 函数返回值的类型。

二、装饰器的类型 Summer IS HERE

接下来,我们就来了解一下装饰器的各种类型。fo028资讯网——每日最新资讯28at.com

Summer:类装饰器

当将函数作为装饰器附加到类时,将收到类构造函数作为第一个参数:fo028资讯网——每日最新资讯28at.com

type ClassDecorator = (value: Function, context: {  kind: "class"  name: string | undefined  addInitializer(initializer: () => void): void}) => Function | void

例如,假设想要使用装饰器向 Rocket 类添加两个属性:fuel 和 isEmpty()。在这种情况下,可以编写以下函数:fo028资讯网——每日最新资讯28at.com

function WithFuel(target: typeof Rocket, context): typeof Rocket {  if (context.kind === "class") {    return class extends target {      fuel: number = 50      isEmpty(): boolean {        return this.fuel == 0      }    }  }}

在确保装饰元素的类型确实是类之后,返回一个具有两个附加属性的新类。或者,可以使用原型对象来动态添加新方法:fo028资讯网——每日最新资讯28at.com

function WithFuel(target: typeof Rocket, context): typeof Rocket {  if (context.kind === "class") {    target.prototype.fuel = 50    target.prototype.isEmpty = (): boolean => {      return this.fuel == 0    }  }}

可以按以下方式使用 WithFuel:fo028资讯网——每日最新资讯28at.com

@WithFuelclass Rocket {}const rocket = new Rocket()console.log((rocket as any).fuel)console.log(`empty? ${(rocket as any).isEmpty()}`)/* Prints:50empty? false*/

可以看到,这里将rocket转换为any类型才能访问新的属性。这是因为装饰器无法影响类型的结构。fo028资讯网——每日最新资讯28at.com

如果原始类定义了一个稍后被装饰的属性,装饰器会覆盖原始值。例如,如果Rocket有一个具有不同值的fuel属性,WithFuel装饰器将会覆盖该值:fo028资讯网——每日最新资讯28at.com

function WithFuel(target: typeof Rocket, context): typeof Rocket {  if (context.kind === "class") {    return class extends target {      fuel: number = 50      isEmpty(): boolean {        return this.fuel == 0      }    }  }}@WithFuelclass Rocket {  fuel: number = 75}const rocket = new Rocket()console.log((rocket as any).fuel)// 50

Summer:方法装饰器

方法装饰器可以用于装饰类方法。在这种情况下,装饰器函数的类型如下:fo028资讯网——每日最新资讯28at.com

type ClassMethodDecorator = (target: Function, context: {  kind: "method"  name: string | symbol  access: { get(): unknown }  static: boolean  private: boolean  addInitializer(initializer: () => void): void}) => Function | void

如果希望在调用被装饰的方法之前或之后执行某些操作时,就可以使用方法装饰器。fo028资讯网——每日最新资讯28at.com

例如,在开发过程中,记录对特定方法的调用或在调用之前/之后验证前置/后置条件可能非常有用。此外,我们还可以影响方法的调用方式,例如通过延迟其执行或限制在一定时间内的调用次数。fo028资讯网——每日最新资讯28at.com

最后,可以使用方法装饰器将一个方法标记为已废弃,并记录一条消息来警告用户,并告知他们应该使用哪个方法代替:fo028资讯网——每日最新资讯28at.com

function deprecatedMethod(target: Function, context) {  if (context.kind === "method") {    return function (...args: any[]) {      console.log(`${context.name} is deprecated and will be removed in a future version.`)      return target.apply(this, args)    }  }}

在这种情况下,deprecatedMethod函数的第一个参数是要装饰的方法。确认它确实是一个方法后(context.kind === "method"),返回一个新的函数,该函数在调用实际方法之前包装被装饰的方法并记录一条警告消息。fo028资讯网——每日最新资讯28at.com

接下来,可以按照以下方式使用装饰器:fo028资讯网——每日最新资讯28at.com

@WithFuelclass Rocket {  fuel: number = 75  @deprecatedMethod  isReadyForLaunch(): Boolean {    return !(this as any).isEmpty()  }}const rocket = new Rocket()console.log(`Is ready for launch? ${rocket.isReadyForLaunch()}`)

在isReadyForLaunch()方法中,引用了通过WithFuel装饰器添加的isEmpty方法。注意,必须将其转换为any类型的实例,与之前一样。当调用isReadyForLaunch()方法时,会看到以下输出,显示警告消息被正确地打印出来:fo028资讯网——每日最新资讯28at.com

isReadyForLaunch is deprecated and will be removed in a future version.Is the ready for launch? true

Summer:属性装饰器

属性装饰器与方法装饰器的类型非常相似:fo028资讯网——每日最新资讯28at.com

type ClassPropertyDecorator = (target: undefined, context: {  kind: "field"  name: string | symbol  access: { get(): unknown, set(value: unknown): void }  static: boolean  private: boolean}) => (initialValue: unknown) => unknown | void

属性装饰器的用例与方法装饰器的用法也非常相似。例如,可以跟踪对属性的访问或将其标记为已弃用:fo028资讯网——每日最新资讯28at.com

function deprecatedProperty(_: any, context) {  if (context.kind === "field") {    return function (initialValue: any) {      console.log(`${context.name} is deprecated and will be removed in a future version.`)      return initialValue    }  }}

代码与为方法定义的 deprecatedMethod 装饰器非常相似,它的用法也是如此。fo028资讯网——每日最新资讯28at.com

Summer:访问器装饰器

与方法装饰器非常相似的是访问器装饰器,它是针对 getter 和 setter 的装饰器:fo028资讯网——每日最新资讯28at.com

type ClassSetterDecorator = (target: Function, context: {  kind: "setter"  name: string | symbol  access: { set(value: unknown): void }  static: boolean  private: boolean  addInitializer(initializer: () => void): void}) => Function | voidtype ClassGetterDecorator = (value: Function, context: {  kind: "getter"  name: string | symbol  access: { get(): unknown }  static: boolean  private: boolean  addInitializer(initializer: () => void): void}) => Function | void

访问器装饰器的定义与方法装饰器的定义类似。例如,可以将 deprecatedMethod 和 deprecatedProperty 修饰合并到一个已弃用的函数中,该函数也支持 getter 和 setter:fo028资讯网——每日最新资讯28at.com

function deprecated(target, context) {  const kind = context.kind  const msg = `${context.name} is deprecated and will be removed in a future version.`  if (kind === "method" || kind === "getter" || kind === "setter") {    return function (...args: any[]) {      console.log(msg)      return target.apply(this, args)    }  } else if (kind === "field") {    return function (initialValue: any) {      console.log(msg)      return initialValue    }  }}

三、装饰器的用例 Summer IS HERE

上面介绍了装饰器是什么以及如何正确使用它们,下面来看看装饰器可以帮助我们解决的一些具体问题。fo028资讯网——每日最新资讯28at.com

Summer:计算执行时间

假设想要估计运行一个函数需要多长时间,以此来衡量应用的性能。可以创建一个装饰器来计算方法的执行时间并将其打印在控制台上:fo028资讯网——每日最新资讯28at.com

class Rocket {  @measure  launch() {    console.log("3... 2... 1...  
                

本文链接:http://www.28at.com/showinfo-26-5177-0.htmlTypeScript 装饰器实用指南!

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 六款开源、免费的简历制作神器,程序员必备!

下一篇: CSS 渐变中的颜色空间和色相插值

标签:
  • 热门焦点
  • Redmi Pad评测:红米充满野心的一次尝试

    从Note系列到K系列,从蓝牙耳机到笔记本电脑,红米不知不觉之间也已经形成了自己颇有竞争力的产品体系,在中端和次旗舰市场上甚至要比小米新机的表现来得更好,正所谓“大丈夫生居
  • 十个可以手动编写的 JavaScript 数组 API

    JavaScript 中有很多API,使用得当,会很方便,省力不少。 你知道它的原理吗? 今天这篇文章,我们将对它们进行一次小总结。现在开始吧。1.forEach()forEach()用于遍历数组接收一参
  • JavaScript学习 -AES加密算法

    引言在当今数字化时代,前端应用程序扮演着重要角色,用户的敏感数据经常在前端进行加密和解密操作。然而,这样的操作在网络传输和存储中可能会受到恶意攻击的威胁。为了确保数据
  • 只需五步,使用start.spring.io快速入门Spring编程

    步骤1打开https://start.spring.io/,按照屏幕截图中的内容创建项目,添加 Spring Web 依赖项,并单击“生成”按钮下载 .zip 文件,为下一步做准备。请在进入步骤2之前进行解压。图
  • 从零到英雄:高并发与性能优化的神奇之旅

    作者 | 波哥审校 | 重楼作为公司的架构师或者程序员,你是否曾经为公司的系统在面对高并发和性能瓶颈时感到手足无措或者焦头烂额呢?笔者在出道那会为此是吃尽了苦头的,不过也得
  • 东方甄选单飞:有些鸟注定是关不住的

    作者:彭宽鸿来源:华尔街科技眼‍‍‍‍‍‍‍‍‍‍东方甄选创始人俞敏洪带队的“7天甘肃行”直播活动已在近日顺利收官。成立后一
  • 到手价3099元起!iQOO Neo8 Pro今日首销:安卓性能最强旗舰

    5月23日,iQOO如期举行了新品发布会,全新的iQOO Neo8系列也正式与大家见面,包含iQOO Neo8和iQOO Neo8 Pro两个版本,其中标准版搭载高通骁龙8+,而Pro版更
  • iQOO Neo8 Pro评测:旗舰双芯加持 最强性能游戏旗舰

    【Techweb评测】去年10月,iQOO推出了一款Neo7手机,该机搭载了联发科天玑9000+,配备独显芯片Pro+,带来了同价位段最佳的游戏体验,一经上市便受到了诸多用
  • 英特尔Xe-HP项目终止,将专注Xe-HPC/HPG系列显卡

    据10 月 31 日消息报道,英特尔高级副总裁兼加速计算系统和图形事业部总经理 表示,Xe-HP“ Arctic Sound” 系列服务器 GPU 已经应用于 oneAPI devcloud 云服
Top