Skip to content

Instantly share code, notes, and snippets.

@rbuckton
Last active August 29, 2015 13:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rbuckton/10752168 to your computer and use it in GitHub Desktop.
Save rbuckton/10752168 to your computer and use it in GitHub Desktop.

Function Decorator

// definition
function functionDecorator(target /*: Function */) /*: Function | void */ { 
  // ...
}

// application
@functionDecorator 
function targetFunction() {}

// desugaring
function targetFunction() {}
targetFunction = __annotate.apply(targetFunction, [functionDecorator]);
// or
targetFunction = [functionDecorator].reduceRight(function (f, d) { return d(f) || f; }, targetFunction);

Class Decorator

// definition
function classDecorator(target /*: Function */) /*: Function | void */ { 
  // ...
}

// application
@classDecorator
class targetClass {
}

// desugaring
class targetClass {
}
targetClass = __annotate.apply(targetClass, [classDecorator]);
// or
targetClass = [classDecorator].reduceRight(function (f, d) { return d(f) || f; }, targetClass);

Member Decorator - Method

// definition
function methodDecorator(target /*: object */, name /*: string */, descriptor /*: PropertyDescriptor */) /*: PropertyDescriptor | void */ {
  // ...
}

// application
class methodClass {
  @methodDecorator
  targetMethod() { }
}

// desugaring
class methodClass { 
  targetMethod() { }
}
__annotate.member(methodClass.prototype, 'targetMethod', [methodDecorator]);
// or
Object.defineProperty(methodClass.prototype, 'targetMethod', [methodDecorator].reduceRight(
    function (p, d) { return d(methodClass.prototype, 'targetMethod', p) || p;}, 
    Object.getOwnPropertyDescriptor(methodClass.prototype, 'targetMethod')))

Member Decorator - Accessor

// definition
function getAccessorDecorator(target /*: object */, name /*: string */, descriptor /*: PropertyDescriptor */) /*: PropertyDescriptor | void */ {
  // ...
}
function setAccessorDecorator(target /*: object */, name /*: string */, descriptor /*: PropertyDescriptor */) /*: PropertyDescriptor | void */ {
  // ...
}

// application
class accessorClass {
  @getAccessorDecorator
  get targetAccessor() { }
  
  @setAccessorDecorator
  set targetAccessor(value) { }
}

// desugaring
class accessorClass {
  get targetAccessor() { }
  set targetAccessor(value) { }
}
__annotate.member(accessorClass.prototype, 'targetAccessor', [getAccessorDecorator, setAccessorDecorator]);
// or
Object.defineProperty(methodClass.prototype, 'targetAccessor', [getAccessorDecorator, setAccessorDecorator].reduceRight(
    function (p, d) { return d(methodClass.prototype, 'targetAccessor', p) || p;}, 
    Object.getOwnPropertyDescriptor(methodClass.prototype, 'targetAccessor')))

Member Decorator - Field

// definition
function fieldDecorator(target /*: object */, name: /*: string */) /*: PropertyDescriptor | void */ {
  // ...
}

// application
class fieldClass {
  @fieldDecorator x = new Point();
}

// desugaring
class fieldClass {
  constructor() {
    // field init
    this.x = new Point();
  }
}
__annotate.member(fieldClass.prototype, 'x', [fieldDecorator]);
// or
[fieldDecorator].forEach(function(d) { d(fieldClass.prototype, 'x'); });

Argument Decorator

// definition
function argumentDecorator(target /*: Function */, index /*: number */) /*: void */ {
  // ...  
}

// application
function argumentFunction(@argumentDecorator arg) {
  print(arg);
}

// desugaring
function argumentFunction(arg) {
  print(arg);
}
__annotate.param(argumentFunction, 0, [argumentDecorator]);
// or
[argumentDecorator].forEach(function (d) { d(argumentFunction, 0) });

Decorator Factory - Function/Class

// definition
function functionDecoratorFactory(arg0, arg1) {
  return function(target /*: Function */) /*: Function | void */ {
    // ...
  }
}

// application
@functionDecoratorFactory(1, 2) 
function targetFunction() {
}

// desugaring
function targetFunction() {}
targetFunction = __annotate.apply(targetFunction, [functionDecoratorFactory(1, 2)]);
// or
targetFunction = [functionDecoratorFactory(1, 2)].reduceRight(function (f, d) { return d(f) || f; }, targetFunction);

Decorator Factory - Member

// definition
function methodDecoratorFactory(arg0, arg1) {
  return function(target /*: object */, name /*: string */, descriptor /*: PropertyDescriptor */) /*: PropertyDescriptor | void */ {
    // ...
  }
}

// application
class methodClass {
  @methodDecoratorFactory(1, 2)
  targetMethod() { }
}

// desugaring
class methodClass { 
  targetMethod() { }
}
__annotate.member(methodClass.prototype, 'targetMethod', [methodDecoratorFactory(1, 2)]);
// or
Object.defineProperty(methodClass.prototype, 'targetMethod', [methodDecoratorFactory(1, 2)].reduceRight(
    function (p, d) { return d(methodClass.prototype, 'targetMethod', p) || p;}, 
    Object.getOwnPropertyDescriptor(methodClass.prototype, 'targetMethod')))

Helpers (downlevel/typescript)

var __annotate = __annotate || {
    apply: function(target, decorators, apply) {
      return decorators.reduceRight(function(target, decorator) {
        return (apply ? apply(decorator, target) : decorator(target)) || target;
      }, target);
    },
    param: function(target, parameterIndex, decorators) {
        __annotate.apply(target, function(decorator) { decorator(target, parameterIndex); });
    },
    member: function(target, propertyKey, decorators) {
        var descriptor = Object.getOwnPropertyDescriptor(target, propertyKey);
        var annotated = __annotate.apply(descriptor, decorators, function(decorator, descriptor) { 
            return decorator(target, propertyKey, descriptor); 
        });
        if (annotated) Object.defineProperty(target, propertyKey, annotated);
    }
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment