reflect-metadata (original) (raw)

0.2.2 • Public • Published a year ago

Metadata Reflection API

NOTE: Now that both Decorators andDecorator Metadata have achieved Stage 3 within TC39, the API proposed below is no longer being considered for standardization. However, this package will continue to support projects that leverage TypeScript's legacy --experimentalDecorators option as some projects may not be able to migrate to use standard decorators.

Installation

npm install reflect-metadata

Usage

ES Modules in NodeJS/Browser, TypeScript/Babel, Bundlers

// - Modifies global Reflect object (or defines one in ES5 runtimes). // - Supports ESM and CommonJS. // - Contains internal polyfills for Map, Set, and WeakMap for older runtimes. import "reflect-metadata";

// - Modifies global Reflect object (or defines one in ES5 runtimes). // - Supports ESM and CommonJS. // - Requires runtime support for "exports" in package.json. // - Does not include internal polyfills. import "reflect-metadata/lite";

CommonJS

// - Modifies global Reflect object (or defines one in ES5 runtimes). // - Contains internal polyfills for Map, Set, and WeakMap for older runtimes. require("reflect-metadata");

// - Modifies global Reflect object (or defines one in ES5 runtimes). // - Requires runtime support for "exports" in package.json. // - Does not include internal polyfills. require("reflect-metadata/lite");

In the Browser via <script>

HTML

Script

// - Makes types available in your editor. ///

Background

Goals

Syntax

class C { @Reflect.metadata(metadataKey, metadataValue) method() { } }

Reflect.defineMetadata(metadataKey, metadataValue, C.prototype, "method");

let obj = new C(); let metadataValue = Reflect.getMetadata(metadataKey, obj, "method");

Semantics

API

// define metadata on an object or property Reflect.defineMetadata(metadataKey, metadataValue, target); Reflect.defineMetadata(metadataKey, metadataValue, target, propertyKey);

// check for presence of a metadata key on the prototype chain of an object or property let result = Reflect.hasMetadata(metadataKey, target); let result = Reflect.hasMetadata(metadataKey, target, propertyKey);

// check for presence of an own metadata key of an object or property let result = Reflect.hasOwnMetadata(metadataKey, target); let result = Reflect.hasOwnMetadata(metadataKey, target, propertyKey);

// get metadata value of a metadata key on the prototype chain of an object or property let result = Reflect.getMetadata(metadataKey, target); let result = Reflect.getMetadata(metadataKey, target, propertyKey);

// get metadata value of an own metadata key of an object or property let result = Reflect.getOwnMetadata(metadataKey, target); let result = Reflect.getOwnMetadata(metadataKey, target, propertyKey);

// get all metadata keys on the prototype chain of an object or property let result = Reflect.getMetadataKeys(target); let result = Reflect.getMetadataKeys(target, propertyKey);

// get all own metadata keys of an object or property let result = Reflect.getOwnMetadataKeys(target); let result = Reflect.getOwnMetadataKeys(target, propertyKey);

// delete metadata from an object or property let result = Reflect.deleteMetadata(metadataKey, target); let result = Reflect.deleteMetadata(metadataKey, target, propertyKey);

// apply metadata via a decorator to a constructor @Reflect.metadata(metadataKey, metadataValue) class C { // apply metadata via a decorator to a method (property) @Reflect.metadata(metadataKey, metadataValue) method() { } }

Alternatives

function ParamTypes(...types) { return (target, propertyKey) => { const symParamTypes = Symbol.for("design:paramtypes"); if (propertyKey === undefined) { target[symParamTypes] = types; } else { const symProperties = Symbol.for("design:properties"); let properties, property; if (Object.prototype.hasOwnProperty.call(target, symProperties)) { properties = target[symProperties]; } else { properties = target[symProperties] = {}; } if (Object.prototype.hasOwnProperty.call(properties, propertyKey)) { property = properties[propertyKey]; } else { property = properties[propertyKey] = {}; } property[symParamTypes] = types; } }; }

Notes

function ParamTypes(...types) { // as propertyKey is effectively optional, its easier to use here return (target, propertyKey) => { Reflect.defineMetadata("design:paramtypes", types, target, propertyKey); }

// vs. having multiple overloads with the target and key in the front: // // return (target, propertyKey) => { // if (propertyKey === undefined) { // Reflect.defineMetadata(target, "design:paramtypes", types); // } // else { // Reflect.defineMetadata(target, propertyKey, "design:paramtypes", types); // } // } // // vs. having a different methods for the class or a property: // // return (target, propertyKey) => { // if (propertyKey === undefined) { // Reflect.defineMetadata(target, "design:paramtypes", types); // } // else { // Reflect.definePropertyMetadata(target, propertyKey, "design:paramtypes", types); // } // } }

Issues