Search code examples
javascripttypescriptdecoratorreflect-metadata

Typescript decorator only works within the same method


I'm trying to use Typescript decorators in one project of mine, but I encountered an strange behaviour that I'm not capable of understand.

It only seems to work if the decorated class is inside the same method that is trying to obtain the metadata:

describe('metadata tests', () => {

    it('should retrieve metadata', () => {

        class Test {
            @TestDecorator('some value')
            property: string;
        }

        const metadata = Reflect.getMetadata('test', new Test(), 'property');
        expect(metadata).toEqual('some value'); //Passes
    });

});

But as soon as I move it outside the method, it does not work anymore:

describe('metadata tests', () => {

    class Test {
        @TestDecorator('some value')
        property: string;
    }

    it('should retrieve metadata', () => {
        const metadata = Reflect.getMetadata('test', new Test(), 'property');
        expect(metadata).toEqual('some value'); //Fails
    });

});

Both tests are using this test decorator:

function TestDecorator(value: any) {
    return function (target: any, propertyKey: string) {
        console.log(`I'm being decorated!`);
        Reflect.defineMetadata('test', value, target, propertyKey);
    };
}

And both are printing to the console...

Also, on both transpiled code I can see the property being decorated correctly and exactly in the same way:

var Test = (function () {
    function Test() {
    }
    __decorate([
        TestDecorator('some value'),
        __metadata("design:type", String)
    ], Test.prototype, "property", void 0);
    return Test;
}());

And here it is my tsconfig.json. I believe is correct (es5, emitDecoratorMetadata and experimentalDecorators):

{
  "compilerOptions": {
    "module": "commonjs",
    "target": "es5",
    "declaration": true,
    "outDir": "dist",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": true
  },
  "exclude": [
    "node_modules",
    "dist"
  ]
}

What am I missing?


Solution

  • For those with the same issue, I don't think this is a solution but, in my case, switching from Webpack to Rollup.js solved the problem...