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
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.
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.
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.
A Decorator is a special kind of declaration that can be applied to classes, methods, accessor, property, or parameter.
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
Tuple
, serialized as Array
class
serialized it as the class constructorEnum
serialized it as Number
Function
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With