TypeScript 1.5,反射和装饰器

mfr*_*het 9 typescript typescript1.5

我想知道是否可以使用反射,更具体地说是关于装饰器,属性,参数或方法的类反射?

这是否可以使用反射器来获取装饰器中使用的信息?

如果有可能,我们该怎么做?另外,为什么我们不能这样做?

编辑:

我有一个应用程序,我使用装饰器,从serviceRegistry注入数据到名为@Inject的装饰器.

在这个应用程序中,我手动填写一个简单的服务注册表,如:

serviceRegistry.push(MyClass1)
serviceRegistry.push(MyClass2)
...
serviceRegistry.push(MyClass100)
Run Code Online (Sandbox Code Playgroud)

目的是能够在运行时使用@ToInject批注修饰的类填充此服务注册表.

这将允许我避免手动填写此注册表,并简单地自动完成此操作.

提前谢谢

Rem*_*sen 12

您可以通过导入reflect-metadata包来使用反射.

import 'reflect-metadata';
Run Code Online (Sandbox Code Playgroud)

将它与TypeScript 1.5一起使用,并将编译器标志emitDecoratorMetadata设置为true.不要忘记包括对它的引用reflect-metadata.d.ts.

您需要实现自己的装饰器:

// declare property decorator
function logType(target : any, key : string) {
  var t = Reflect.getMetadata("design:type", target, key);
  console.log(`${key} type: ${t.name}`);
}

class Demo{ 
  @logType // apply property decorator
  public attr1 : string;
}
Run Code Online (Sandbox Code Playgroud)

它将登录控制台:

attr1 type: String
Run Code Online (Sandbox Code Playgroud)

另一个例子:

// declare parameter decorator
function logParamTypes(target : any, key : string) {
  var types = Reflect.getMetadata("design:paramtypes", target, key);
  var s = types.map(a => a.name).join();
  console.log(`${key} param types: ${s}`);
}  

class Foo {}
interface IFoo {}

class Demo{ 
  @logParameters // apply parameter decorator
  doSomething(
    param1 : string,
    param2 : number,
    param3 : Foo,
    param4 : { test : string },
    param5 : IFoo,
    param6 : Function,
    param7 : (a : number) => void,
  ) : number { 
      return 1
  }
}
Run Code Online (Sandbox Code Playgroud)

它将登录控制台:

doSomething param types: String, Number, Foo, Object, Object, Function, Function
Run Code Online (Sandbox Code Playgroud)

请注意,接口IFoo和对象文字{ test : string}被序列化为Object.序列化规则是:

  • number 序列化为 Number
  • string 序列化为 String
  • boolean 序列化为 Boolean
  • any 序列化为 Object
  • void 序列化为 undefined
  • Array 序列化为 Array
  • 如果是Tuple,序列化为Array
  • 如果class将它序列化为类构造函数
  • 如果Enum序列化为Number
  • 如果至少有一个呼叫签名,则序列化为 Function
  • 否则序列化为Object(包括接口)

接口和对象文字可能在将来通过复杂类型序列化进行序列化,但此功能目前不可用.

您还可以使用以下命令获取函数的返回类型:

Reflect.getMetadata("design:returntype", target, key);
Run Code Online (Sandbox Code Playgroud)

如果您需要有关装饰器的更多信息,您可以阅读:TypeScript中的装饰器和元数据反射:从新手到专家

  • Reflect-metadata包含npm模块中的.d.ts文件.当我写这个答案时,需要对dts文件使用`/// <reference path ="">`.今天,如果您使用TS> = 2.0,则不需要这样做. (2认同)