从我记事起,装饰器几乎就已经是 ECMAScript 的一部分了。这些漂亮的工具让我们能够以可重用的方式修改类和成员。他们已经在 TypeScript 中出现了一段时间——尽管是在实验旗帜下。尽管装饰器的第 2 阶段迭代始终处于实验阶段,但装饰器已广泛应用于MobX、Angular、Nest和TypeORM等库中。TypeScript 5.0 的装饰器与ECMAScript 提案完全同步,ECMAScript 提案已经为黄金时段做好了准备,处于第 3 阶段。
装饰器让我们可以设计一个函数来调整类及其方法的行为。想象一下需要将一些调试语句潜入我们的方法中。在 TypeScript 5.0 之前,我们必须在每个方法中手动复制和粘贴调试语句。使用装饰器,我们只需完成一次工作,并且将通过装饰器附加的每个方法来支持更改。
假设我们想要创建一个装饰器来记录给定方法已被弃用:
class Card { constructor(public suit: Suit, public rank: Rank) { this.suit = suit; this.rank = rank; } get name(): CardName { return `${this.rank} of ${this.suit}`; } @deprecated // This is a decorator! getValue(): number { if (this.rank === 'Ace') return 14; if (this.rank === 'King') return 13; if (this.rank === 'Queen') return 12; if (this.rank === 'Jack') return 11; return this.rank; } // The new way to do it! get value(): number { if (this.rank === 'Ace') return 14; if (this.rank === 'King') return 13; if (this.rank === 'Queen') return 12; if (this.rank === 'Jack') return 11; return this.rank; } } const card = new Card('Spades', 'Queen'); card.getValue();
card.getValue()
我们希望每当调用时都会将警告消息记录到控制台。我们可以按如下方式实现上面的装饰器:
const deprecated = <This, Arguments extends any[], ReturnValue>( target: (this: This, ...args: Arguments) => ReturnValue, context: ClassMethodDecoratorContext< This, (this: This, ...args: Arguments) => ReturnValue >, ) => { const methodName = String(context.name); function replacementMethod(this: This, ...args: Arguments): ReturnValue { console.warn(`Warning: '${methodName}' is deprecated.`); return target.call(this, ...args); } return replacementMethod; };
乍一看这可能有点令人困惑,但让我们来分解一下:
我们的装饰器函数有两个参数:
target
和context
。target
是我们正在装饰的方法本身。context
是有关该方法的元数据。我们返回一些具有相同签名的方法。
在本例中,我们调用
console.warn
以记录弃用通知,然后调用该方法。
该ClassMethodDecorator
类型具有以下属性:
kind
:装饰属性的类型。在上面的示例中,这将是method
,因为我们正在 a 实例上修饰一个方法Card
。name
: 财产名称。在上面的例子中,这是getValue
.static
:指示类元素是静态 (true
) 还是实例 (false
) 元素的值。private
:指示类元素是否具有私有名称的值。access
:可用于在运行时访问类元素的当前值的对象。has
:确定对象是否具有与装饰元素同名的属性。get
:调用所提供对象上的 setter。
装饰器提供了方便的语法糖来添加日志消息(就像我们在上面的示例中所做的那样)以及许多其他常见用例。例如,我们可以创建一个装饰器,自动将方法绑定到当前实例,或者修改方法或类的属性描述符。
网友评论文明上网理性发言 已有0人参与
发表评论: