When angulat allows annotations, it has three parameters :
1) Direct API
// Prefer the direct API. if ((<any>typeOrFunc).annotations && (<any>typeOrFunc).annotations !== parentCtor.annotations) { let annotations = (<any>typeOrFunc).annotations; if (typeof annotations === 'function' && annotations.annotations) { annotations = annotations.annotations; } return annotations; }
We usually use this API when writing code in ES5.
MyComponent.annotations = [ new ng.Component({...}) ]
2) tcickle API symbol
// API of tsickle for lowering decorators to properties on the class. if ((<any>typeOrFunc).decorators && (<any>typeOrFunc).decorators !== parentCtor.decorators) { return convertTsickleDecoratorIntoMetadata((<any>typeOrFunc).decorators); }
Thus, angular reads annotations from the @angular/(core|material...) libraries. angular compiles libraries this way because it helps optimize the package. For example, we donβt need to send decorators helpers like _decorate, __metadata , and the code will be executed faster.
To do this, angular uses tslib when creating the library by running tsc with the --importHelpers options https://github.com/angular/angular/blob/master/build.sh#L127 .
Angular stuff does the same https://github.com/angular/material2/blob/master/tools/package-tools/rollup-helpers.ts#L9-L11
// Import tslib rather than having TypeScript output its helpers multiple times. // See https://github.com/Microsoft/tslib 'tslib': 'tslib',
3) Using Reflect
// API for metadata created by invoking the decorators. if (this._reflect && this._reflect.getOwnMetadata) { return this._reflect.getOwnMetadata('annotations', typeOrFunc); }
This API is used when we use metadata emitted by typescript.
To make sure that you get the metadata correctly, you can use a function, for example:
declare let Reflect: any; function getAnnotations(typeOrFunc: Type<any>): any[]|null { // Prefer the direct API. if ((<any>typeOrFunc).annotations) { let annotations = (<any>typeOrFunc).annotations; if (typeof annotations === 'function' && annotations.annotations) { annotations = annotations.annotations; } return annotations; } // API of tsickle for lowering decorators to properties on the class. if ((<any>typeOrFunc).decorators) { return convertTsickleDecoratorIntoMetadata((<any>typeOrFunc).decorators); } // API for metadata created by invoking the decorators. if (Reflect && Reflect.getOwnMetadata) { return Reflect.getOwnMetadata('annotations', typeOrFunc); } return null; } function convertTsickleDecoratorIntoMetadata(decoratorInvocations: any[]): any[] { if (!decoratorInvocations) { return []; } return decoratorInvocations.map(decoratorInvocation => { const decoratorType = decoratorInvocation.type; const annotationCls = decoratorType.annotationCls; const annotationArgs = decoratorInvocation.args ? decoratorInvocation.args : []; return new annotationCls(...annotationArgs); }); } const annotations = getAnnotations(AppModule);
Update:
The API for metadata created when decorators were called was changed to 5.0.0-beta.
const ANNOTATIONS = '__annotations__'; // API for metadata created by invoking the decorators. if (typeOrFunc.hasOwnProperty(ANNOTATIONS)) { return (typeOrFunc as any)[ANNOTATIONS]; } return null;