Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeScript 1.5, reflection and decorator

I was wondering if it was possible to use reflection, and more particularly class reflection concerning decorator, on property, on parameter or on method ?

Is this possible to use reflector to get the information used in the decorators ?

If it's possible, how can we do that ? Else, why cant we do that ?

EDIT :

I have an application in which I use decorators, to inject data, from a serviceRegistry, to a decorator called @Inject.

In this application, I fill a simple service registry by hand, like :

serviceRegistry.push(MyClass1)
serviceRegistry.push(MyClass2)
...
serviceRegistry.push(MyClass100)

The aim is to be able to fill this service registry with classes that are decorated with @ToInject annotation, at runtime.

This will permit me to avoid to fill this registry by hand, and to automate this simply.

THanks for advance

like image 512
mfrachet Avatar asked Jun 05 '15 03:06

mfrachet


People also ask

Does TypeScript have reflection?

Summary. The reality is that Typescript Reflection is very poor. In order to get a very basic set of Reflection features — we need to make a number of hacky solutions. Other than Dependency Injection tools, I see no other use for this limited functionality.

Are decorators still experimental in TypeScript?

As of writing this guide, decorators are still an experimental feature in TypeScript. To enable this feature, set the experimentalDecorators compiler flag either on the command line or in your tsconfig. json file.

Are decorators useful in TypeScript?

Decorators provide a way to add both annotations and a meta-programming syntax for class declarations and members. Decorators are a stage 2 proposal for JavaScript and are available as an experimental feature of TypeScript. NOTE Decorators are an experimental feature that may change in future releases.

Is Decorator a type variable in TypeScript?

A Decorator is a special kind of declaration that can be applied to classes, methods, accessor, property, or parameter.


1 Answers

You can use reflection by importing the reflect-metadata package.

import 'reflect-metadata';

Use it with TypeScript 1.5 and the compiler flag emitDecoratorMetadata set to true. Don't forget including a reference to reflect-metadata.d.ts as well.

You need to implement your own decorators:

// 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;
}

It will log in console:

attr1 type: String

Another example:

// 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
  }
}

It will log in console:

doSomething param types: String, Number, Foo, Object, Object, Function, Function

Notice the that interfaces IFoo and object literal { test : string} are serialized as Object. The serialization rules are:

  • number serialized as Number
  • string serialized as String
  • boolean serialized as Boolean
  • any serialized as Object
  • void serializes as undefined
  • Array serialized as Array
  • If a Tuple, serialized as Array
  • If a class serialized it as the class constructor
  • If an Enum serialized it as Number
  • If has at least one call signature, serialized as Function
  • Otherwise serialized as Object (Including interfaces)

Interfaces and object literals may be serialize in the future via complex type serialization but this feature is not available at this time.

You can also get the return type of a function using:

Reflect.getMetadata("design:returntype", target, key);

If you need more info about decorators you can read : Decorators & metadata reflection in TypeScript: From Novice to Expert

like image 119
Remo H. Jansen Avatar answered Oct 27 '22 17:10

Remo H. Jansen