Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

reflect-metadata and querying the object for decorators

Tags:

I have a decorator that simply does nothing:

export function myDecorator(target: any, key: string) {
   var t = Reflect.getMetadata("design:type", target, key);
}

I use this decorator with a property of a class:

export class SomeClass {

    @globalVariable
    someProperty: string;

    @globalVariable
    fakeProperty: number;
}

Now, what I want to do is, get all the properties of the class decorated with the @globalVariable decorator.

I tried using "reflect-metadata" with:

Reflect.getMetadata('globalVariable', this);

but all I get is "undefined". Is this possible with reflect-metadata or am I getting this totally wrong?

like image 970
Élodie Petit Avatar asked May 02 '17 08:05

Élodie Petit


2 Answers

Property decorators are called once per property definition within a class, when the class is defined.

This means that if you decorate the properties in SomeClass with @myDecorator:

export class SomeClass {
    @myDecorator
    someProperty: string;
}

Then the myDecorator function will be called with:
target: ( the SomeClass definition )
key : ( the name of the property )

When you enable metadata through the "emitDecoratorMetadata" property, the TypeScript compiler will generate the following metadata properties:

'design:type', 'design:paramtypes' and 'design:returntype'.

This then allows you to call Reflect.getMetadata with any of the above keys. i.e:

Reflect.getMetadata('design:type', ...)
Reflect.getMetadata('design:paramtypes',...)
Reflect.getMetadata('design:returntype', ...)

You cannot call Reflect.getMetadata with the name of the decorator.

like image 174
blorkfish Avatar answered Sep 22 '22 10:09

blorkfish


What you need is to implement globalVariable in the following way:

function globalVariable(target: any, propertyKey: string | Symbol): void {
    let variables = Reflect.getOwnMetadata("globalVariable", target.constructor) || [];
    variables.push(propertyKey);
    Reflect.defineMetadata("globalVariable", variables, target.constructor);
}

Then, on run time, you'll be able to call

Reflect.getMetadata('globalVariable', this);

as you wanted.

like image 40
RotemGe Avatar answered Sep 25 '22 10:09

RotemGe