55 lines
2.0 KiB
TypeScript
Raw Normal View History

/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Type} from '../type';
interface TypeWithMetadata extends Type<any> {
decorators?: any[];
ctorParameters?: any[];
propDecorators?: {[field: string]: any};
}
/**
* Adds decorator, constructor, and property metadata to a given type via static metadata fields
* on the type.
*
* These metadata fields can later be read with Angular's `ReflectionCapabilities` API.
*
* Calls to `setClassMetadata` can be marked as pure, resulting in the metadata assignments being
* tree-shaken away during production builds.
*/
export function setClassMetadata(
type: Type<any>, decorators: any[] | null, ctorParameters: any[] | null,
propDecorators: {[field: string]: any} | null): void {
const clazz = type as TypeWithMetadata;
if (decorators !== null) {
if (clazz.decorators !== undefined) {
clazz.decorators.push(...decorators);
} else {
clazz.decorators = decorators;
}
}
if (ctorParameters !== null) {
// Rather than merging, clobber the existing parameters. If other projects exist which use
// tsickle-style annotations and reflect over them in the same way, this could cause issues,
// but that is vanishingly unlikely.
clazz.ctorParameters = ctorParameters;
}
if (propDecorators !== null) {
// The property decorator objects are merged as it is possible different fields have different
// decorator types. Decorators on individual fields are not merged, as it's also incredibly
// unlikely that a field will be decorated both with an Angular decorator and a non-Angular
// decorator that's also been downleveled.
if (clazz.propDecorators !== undefined) {
clazz.propDecorators = {...clazz.propDecorators, ...propDecorators};
} else {
clazz.propDecorators = propDecorators;
}
}
}