Closed
Description
ES7 proposal
The ES7 proposal for decorators can be found here: https://github.com/wycats/javascript-decorators
The ES7 proposal serves as the base of this proposal. Below are notes about how the type system
Decorator targets:
Class constructor
@F("color")
@G
class Foo {
}
desugars to:
var Foo = (function () {
function Foo() {
}
Foo = __decorate([F("color"), G], Foo);
return Foo;
})();
Methods
class Foo {
@F(color)
@G
bar() { }
}
desugars to:
var Foo = (function () {
function Foo() {
}
Foo.prototype.bar = function () {
};
Object.defineProperty(Foo.prototype, "bar", __decorate([F(color), G], Foo.prototype, "bar", Object.getOwnPropertyDescriptor(Foo.prototype, "bar")));
return Foo;
})();
Static method
class Foo {
@F("color")
@G
static sMethod() {}
}
desugars to:
var Foo = (function () {
function Foo() {
}
Foo.sMethod = function () {
};
Object.defineProperty(Foo, "sMethod", __decorate([F("color"), G], Foo, "sMethod", Object.getOwnPropertyDescriptor(Foo, "sMethod")));
return Foo;
})();
Properties
class Foo {
@F("color")
@G
prop: number;
}
desugars to:
var Foo = (function () {
function Foo() {
}
__decorate([F("color"), G], Foo.prototype, "prop");
return Foo;
})();
Method/Accessor formal parameter
class Foo {
method(@G a, @F("color") b) {}
}
desugars to:
var Foo = (function () {
function Foo() {
}
Foo.prototype.method = function (a, b) {
};
__decorate([G], Foo.prototype, "method", 0);
__decorate([F("color")], Foo.prototype, "method", 1);
return Foo;
})();
Where the __decorate is defined as:
var __decorate = this.__decorate || function (decorators, target, key, value) {
var kind = typeof (arguments.length == 2 ? value = target : value);
for (var i = decorators.length - 1; i >= 0; --i) {
var decorator = decorators[i];
switch (kind) {
case "function": value = decorator(value) || value; break;
case "number": decorator(target, key, value); break;
case "undefined": decorator(target, key); break;
case "object": value = decorator(target, key, value) || value; break;
}
}
return value;
};
Decorator signatures:
A valid decorator should be:
- Assignable to one of the Decorator types (ClassDecorator | PropertyDecorator | MethodDecorator | ParameterDecorator) as described below.
- Return a value (in the case of class decorators and method decorator) that is assignable to the decorated value.
declare type ClassDecorator = <TFunction extends Function>(target: TFunction) => TFunction | void;
declare type PropertyDecorator = (target: Object, propertyKey: string | symbol) => void;
declare type MethodDecorator = <T>(target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>) => TypedPropertyDescriptor<T> | void;
declare type ParameterDecorator = (target: Function, propertyKey: string | symbol, parameterIndex: number) => void;
Notes:
- Decorating a function declaration is not allowed as it will block hoisting the function to the top of the scope, which is a significant change in semantics.
- Decorating function expressions and arrow functions are not supported. The same effect can be achived by applying the decorator function as
var x = dec(function () { });
- Decorating function formal parameters is currently not part of the ES7 proposal.
- Decorators are not allowed when targeting ES3