TypeScript class decorator that modifies object in

2019-03-20 03:49发布

I'm making a plugin for Aurelia and need a class decorator that

  1. adds attributes to the new object instance, and
  2. calls an external function with the new object as an argument.

I've looked through examples, and so far I've put together ("pseudo-ish" code)

return function addAndCall(target: any): any {
    var original = target;

    var newConstructor = function (...args) {
        original.apply(this, args);
        this.newAttribute = "object instance value";
        ExternalModule.externalFunction(this);
    };

    newConstructor.prototype = Object.create(original.prototype);
    newConstructor.prototype.constructor = original;

    return <any>newConstructor;
}

but

  • I'm not entirely clear on the details here (or what is actually needed), and
  • it might not work properly since I'm getting Aurelia errors when using objects instantiated from classes with this decorator (and I suspect it's my decorator rather than the Aurelia framework that's buggy).

Any help and explanation would be greatly appreciated!

2条回答
beautiful°
2楼-- · 2019-03-20 04:09

Why not just assign those properties to the prototype, and subsequently assign to the instance on first invocation

// decorator
function addAndCall(cb: Function, newField: string) {
  // cb is now available in the decorator
  return function(ctor: Function): void {

    Object.defineProperty(ctor.prototype, newField, {
      value: function(...args: any[]) {
        return Object.defineProperty(this, newField, {

          value: function(...args: any[]) {
            console.log(newField, ...args);
          }

        })[newField](...args);
      }
    });
    cb(ctor);
  }
}

let callMe = (decoratedCtor) => console.log(decoratedCtor);
@addAndCall(callMe, 'propertyName')
class AddToMe {}

let addToMe = new AddToMe();
(<any>addToMe).propertyName(1, 2);
查看更多
爱情/是我丢掉的垃圾
3楼-- · 2019-03-20 04:13

Here's a working version:

function addAndCall(target: any) {
    var original = target;

    function construct(constructor, args) {
        var c: any = function () {
            this.newAttribute = "object instance value";
            ExternalModule.externalFunction(this);
            return constructor.apply(this, args);;
        }

        c.prototype = constructor.prototype;
        return new c();
    }

    var f: any = function (...args) {
        return construct(original, args);
    }

    f.prototype = original.prototype;
    return f;
}

(code in playground)

查看更多
登录 后发表回答