Reflect.js
function defineMetadata(metadataKey, metadataValue, target, propertyKey) {
            if (!IsObject(target))
                throw new TypeError();
            if (!IsUndefined(propertyKey))
                propertyKey = ToPropertyKey(propertyKey);
            return OrdinaryDefineOwnMetadata(metadataKey, metadataValue, target, propertyKey);
        }
function defineMetadata(metadataKey, metadataValue, target, propertyKey) {
            if (!IsObject(target))
                throw new TypeError();
            if (!IsUndefined(propertyKey))
                propertyKey = ToPropertyKey(propertyKey);
            return OrdinaryDefineOwnMetadata(metadataKey, metadataValue, target, propertyKey);
        }
function defineMetadata ( metadataKey , metadataValue , target , propertyKey ) { if ( ! IsObject ( target ) ) throw new TypeError ( ) ; if ( ! IsUndefined ( propertyKey ) ) propertyKey = ToPropertyKey ( propertyKey ) ; return OrdinaryDefineOwnMetadata ( metadataKey , metadataValue , target , propertyKey ) ; }
Define a unique metadata entry on the target.
@param metadataKey A key used to store and retrieve metadata.
@param metadataValue A value that contains attached metadata.
@param target The target object on which to define metadata.
@param propertyKey (Optional) The property key for the target.
@example

class Example {
// property declarations are not part of ES6, though they are valid in TypeScript:
// static staticProperty;
// property;

constructor(p) { }
static staticMethod(p) { }
method(p) { }
}

// constructor
Reflect.defineMetadata("custom:annotation", options, Example);

// property (on constructor)
Reflect.defineMetadata("custom:annotation", options, Example, "staticProperty");

// property (on prototype)
Reflect.defineMetadata("custom:annotation", options, Example.prototype, "property");

// method (on constructor)
Reflect.defineMetadata("custom:annotation", options, Example, "staticMethod");

// method (on prototype)
Reflect.defineMetadata("custom:annotation", options, Example.prototype, "method");

// decorator factory as metadata-producing annotation.
function MyAnnotation(options): Decorator {
return (target, key?) => Reflect.defineMetadata("custom:annotation", options, target, key);
}
Define a unique metadata entry on the target . @param metadataKey A key used to store and retrieve metadata . @param metadataValue A value that contains attached metadata . @param target The target object on which to define metadata . @param propertyKey ( Optional ) The property key for the target . @example