如何实现打字稿装饰器? [英] How to implement a typescript decorator?

查看:71
本文介绍了如何实现打字稿装饰器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

TypeScript 1.5 具有装饰器

有人可以提供一个简单的示例来演示

Could someone provide a simple example demonstrating the proper way to implement a decorator and describe what the arguments in the possible valid decorator signatures mean?

declare type ClassDecorator = <TFunction extends Function>(target: TFunction) => TFunction | void;
declare type PropertyDecorator = (target: Object, propertyKey: string | symbol) => void;
declare type MethodDecorator = <T>(target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>) => TypedPropertyDescriptor<T> | void;
declare type ParameterDecorator = (target: Function, propertyKey: string | symbol, parameterIndex: number) => void;

此外,在实现装饰器时,是否还应考虑最佳实践考虑? p>

Additionally, are there any best practice considerations that should be kept in mind while implementing a decorator?

推荐答案

我最终与装饰员一起玩,决定将我想出的东西记录在案,然后再写给任何想利用它的人出来。如果发现任何错误,请随时进行编辑。

I ended up playing around with decorators and decided to document what I figured out for anyone who wants to take advantage of this before any documentation comes out. Please feel free to edit this if you see any mistakes.


  • 在声明类时(而不是在实例化对象时)调用装饰器。

  • 可以在相同的类/属性/方法/参数上定义多个装饰器。

  • 不允许在构造函数上使用装饰器。


有效的装饰器应为:

A valid decorator should be:


  1. 可分配给以下一种装饰类型( ClassDecorator | PropertyDecorator | MethodDecorator | ParameterDecorator )。

  2. 返回可分配给装饰值的值(对于类装饰器和方法装饰器而言)。

  1. Assignable to one of the Decorator types (ClassDecorator | PropertyDecorator | MethodDecorator | ParameterDecorator).
  2. Return a value (in the case of class decorators and method decorator) that is assignable to the decorated value.

参考






方法/形式访问器装饰器



实现参数:


Method / Formal Accessor Decorator

Implementation parameters:


  • target :该类的原型( Object
  • propertyKey :方法的名称( string | 符号 )。

  • 描述符:A TypedPropertyDescriptor —如果您不熟悉描述符的键,我建议在本文档中阅读有关此内容的信息。在 Object.defineProperty (这是第三个参数)上。

  • target: The prototype of the class (Object).
  • propertyKey: The name of the method (string | symbol).
  • descriptor: A TypedPropertyDescriptor — If you're unfamiliar with a descriptor's keys, I would recommend reading about it in this documentation on Object.defineProperty (it's the third parameter).

使用:

class MyClass {
    @log
    myMethod(arg: string) { 
        return "Message -- " + arg;
    }
}

实施:

function log(target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) {
    const originalMethod = descriptor.value; // save a reference to the original method

    // NOTE: Do not use arrow syntax here. Use a function expression in 
    // order to use the correct value of `this` in this method (see notes below)
    descriptor.value = function(...args: any[]) {
        // pre
        console.log("The method args are: " + JSON.stringify(args));
        // run and store result
        const result = originalMethod.apply(this, args);
        // post
        console.log("The return value is: " + result);
        // return the result of the original method (or modify it before returning)
        return result;
    };

    return descriptor;
}

输入:

new MyClass().myMethod("testing");

输出:


方法args为:[ testing]

The method args are: ["testing"]

返回值为:消息-测试

注意:


  • 设置描述符的值时请勿使用箭头语法。 this 的上下文不是您的实例。

  • 修改原始描述符比通过返回新描述符覆盖当前描述符要好。这使您可以使用多个装饰器来编辑描述符,而不会覆盖其他装饰器的操作。这样做可以让您同时使用 @enumerable(false) @log 之类的示例(例如:< a href = https://www.typescriptlang.org/Playground/#src=class%20FooBar%20%7B%0D%0A%20%20%20%20%40log%0D%0A%09%40enumerable(false )%0D%0A%20%20%20%20public%20foo(arg)%3A%20void%20%7B%0D%0A%09%09%2F%2F%20this%20code%20will%20incently%20output%20 %22foo%22%20因为%20the%20log%20decorator%20OVERWRITES%20the%20描述符%0D%0A%20%20%20%20%20%20%20%20%20for%20(var%20prop%20in%20this)% 20%7B%0D%0A%09%09%09console.log(prop)%3B%0D%0A%09%09%7D%0D%0A%20%20%20%20%7D%0D%0A%7D %0D%0A%0D%0Afunction%20log(target%3A%20Object%2C%20propertyKey%3A%20string%2C%20value%3A%20TypedPropertyDescriptor%3Cany%3E)%20%7B%0D%0A%09return%20% 7B%0D%0A%20%20%20%20%20%20%20%20value%3A%20function%20(... args%3A%20any%5B%5D)%20%7B%0D%0A% 20%20%20%20%20%20%20%20%20%20%20%20var%20a%20%3D%20args.map(a%20%3D%3E%20JSON.stringify(a))。 join()%3B%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20var%20result%20%3D%20value .value.apply(this%2C%20args)%3B%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20var%20r%20%3D%20JSON stringify(result)%3B%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20console.log(%60Call%3A%20%24%7BpropertyKey%7D( %24%7Ba%7D)%20%3D%3E%20%24%7Br%7D%60)%3B%0D%0A%20%20%20%20%20%20%20%20%20%20%20 %20%20return%20result%3B%0D%0A%20%20%20%20%20%20%20%20%20%7D%0D%0A%20%20%20%20%20%7D%3B%0D%0A %7D%0D%0A%0D%0Afunction%20enumerable(isEnumerable%3A%20boolean)%20%7B%0D%0A%20%20%20%20return%20(target%3A%20Object%2C%20propertyKey%3A% 20string%2C%20descriptor%3A%20TypedPropertyDescriptor%3Cany%3E)%20%3D%3E%20%7B%0D%0A%20%20%20%20%20%20%20%20%20descriptor.enumerable%20%3D %20isEnumerable%3B%0D%0A%20%20%20%20%20%20%20%20return%20描述符%3B%0D%0A%20%20%20%20%20%7D%0D%0A%7D%0D %0A%0D%0Avar%20test%20%3D%20new%20FooBar()%3B%0D%0A%0D%0Atest.foo(%22asdf%22)%3B rel = noreferrer>错误 vs

  • 有用 TypedPropertyDescriptor 的类型参数可用于限制哪些方法签名(方法示例)或访问者签名(访问者示例)可以放置装饰器。

  • Do not use arrow syntax when setting the descriptor's value. The context of this will not be the instance's if you do.
  • It's better to modify the original descriptor than overwriting the current one by returning a new descriptor. This allows you to use multiple decorators that edit the descriptor without overwriting what another decorator did. Doing this allows you to use something like @enumerable(false) and @log at the same time (Example: Bad vs Good)
  • Useful: The type argument of TypedPropertyDescriptor can be used to restrict what method signatures (Method Example) or accessor signatures (Accessor Example) the decorator can be put on.

使用参数时,必须声明带有装饰器参数的函数,然后返回带有示例签名且不带参数的函数。

When using arguments, you must declare a function with the decorator's parameters then return a function with the signature of the example without arguments.

class MyClass {
    @enumerable(false)
    get prop() {
        return true;
    }
}

function enumerable(isEnumerable: boolean) {
    return (target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) => {
        descriptor.enumerable = isEnumerable;
        return descriptor;
    };
}






静态方法装饰器



类似于方法修饰器,但有一些区别:


Static Method Decorator

Similar to a method decorator with some differences:


  • target 参数是构造函数本身而不是原型。

  • 描述符是在构造函数而非原型上定义的。

  • Its target parameter is the constructor function itself and not the prototype.
  • The descriptor is defined on the constructor function and not the prototype.
@isTestable
class MyClass {}

实现参数:


  • target :装饰器的声明类( TFunction扩展了Function )。

  • target: The class the decorator is declared on (TFunction extends Function).

示例用法:使用元数据api将信息存储在类上。

Example use: Using the metadata api to store information on a class.

class MyClass {
    @serialize
    name: string;
}

执行参数:


  • target :该类的原型( Object )。

  • propertyKey :属性的名称(字符串 | 符号 )。

  • target: The prototype of the class (Object).
  • propertyKey: The name of the property (string | symbol).

示例用法:创建一个 @serialize( serializedName)装饰器,并将属性名称添加到要序列化的属性列表中。

Example use: Creating a @serialize("serializedName") decorator and adding the property name to a list of properties to serialize.

class MyClass {
    myMethod(@myDecorator myParameter: string) {}
}

实现参数:


  • target :该类的原型( Function - 功能不再起作用。您现在应该在此处使用 any Object 以便在任何类中使用装饰器。或指定要限制其使用的类类型)

  • propertyKey :方法的名称(字符串 | 符号 )。

  • parameterIndex :列表中参数的索引函数的参数( number )。

  • target: The prototype of the class (Function—it seems Function doesn't work anymore. You should use any or Object here now in order to use the decorator within any class. Or specify the class type(s) you want to restrict it to)
  • propertyKey: The name of the method (string | symbol).
  • parameterIndex: The index of parameter in the list of the function's parameters (number).

简单示例

  • Memoize decorator - Method, Get/Set Accessor decorator example

这篇关于如何实现打字稿装饰器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆