If I use a decorator in my class the decorator is evaluated when importing the class. Here is the small example:
@NgModule({ ... })
export class BModule { ... }
Transpiled as:
var BModule = (function () {
function BModule() {
}
BModule = __decorate([ <---------- decorators are applied here
core_1.NgModule({...})
], BModule);
return BModule;
}());
exports.BModule = BModule;
However, when the module or any other decorator is applied in the @angular
bundles the output is the following:
var HttpClientModule = (function () {
function HttpClientModule() {
}
return HttpClientModule;
}());
HttpClientModule.decorators = [
{ type: _angular_core.NgModule, args: [{ ... },] },
];
As you can see, the decorators are not applied here. They are just saved in the decorators
property. Why is it different from my code?
The reason I'm asking is that when importing my decorated classes I expect it to have decorators applied and so using Reflect
is possible:
const providers = Reflect.getOwnMetadata('annotations', BModule);
However, it doesn't work this way with decorated classes from the @angular
packages.
When angulat resolves annotations it has three options:
1) Direct API
We usually use this API when write code in ES5
2) API of tsickle
This way angular reads annotations from
@angular/(core|material...)
libraries. Angular compiles libraries this way because it helps to optimize bundle. For example we do not need to ship decorator helpers like_decorate, __metadata
and the code will be executed faster.For that angular uses
tslib
when building library by running tsc with--importHelpers
options https://github.com/angular/angular/blob/master/build.sh#L127.Angular material does the same thing https://github.com/angular/material2/blob/master/tools/package-tools/rollup-helpers.ts#L9-L11
3) Using Reflect
This API is used when we use metadata emitted by typescript
To ensure you will get metadata correctly you can consider using function like:
Update:
API for metadata created by invoking the decorators was changed in 5.0.0-beta.4