Nick2324
Nick2324

Reputation: 45

How to manage "this" binding in method decorator?

I've been trying to use this inside a decorated method with no success. I saw how the compiler translates this and actually it's not using the proper this, but a variable called _this that is assigned when this isn't bind to anything.

I tried to bind descriptor.value to target, but it didn't work

Here is my code:

export function PathMethod<T>(path: string): Function {
    return (target: ServicioRest<T>, propertyKey: string, descriptor: PropertyDescriptor): void => {
        const original: Function = descriptor.value;
        descriptor.value = (entity: T): T => {
            const initialPath: string = this.path;
            if (!this.path.endsWith('/')) {
                this.path += '/';
            }
            this.path += path;
            const result: T = original(entity);
            this.path = initialPath;
            return result;
        };
    };
}

And the translation is being this:

function PathMethod(path) {
    var _this = this;
    return function (target, propertyKey, descriptor) {
        /** @type {?} */
        var original = descriptor.value;
        descriptor.value = function (entity) {
            /** @type {?} */
            var initialPath = _this.path;
            if (!_this.path.endsWith('/')) {
                _this.path += '/';
            }
            _this.path += path;
            /** @type {?} */
            var result = original(entity);
            _this.path = initialPath;
            return result;
        };
    };
}

But actually the translation should've been this:

function PathMethod(path) {
    return function (target, propertyKey, descriptor) {
        /** @type {?} */
        var original = descriptor.value;
        descriptor.value = function (entity) {
            /** @type {?} */
            var initialPath = this.path;
            if (!this.path.endsWith('/')) {
                this.path += '/';
            }
            this.path += path;
            /** @type {?} */
            var result = original(entity);
            this.path = initialPath;
            return result;
        };
    };
}

Does somebody know how to manage to that solution? Is there anything wrong with my code?

Upvotes: 0

Views: 255

Answers (1)

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 249646

If you don't want to capture this from the declaration context use a regular function not an arrow function. The _this ts inserts is to emulate the es2015 arrow function behavior. Regular function expression and declarations don't do this. While the => is shorter, you should always consider this behavior when dealing between the two see docs.

export function PathMethod<T>(path: string): Function {
    return (target: ServicioRest<T>, propertyKey: string, descriptor: PropertyDescriptor): void => {
        const original: Function = descriptor.value;
        descriptor.value = function (entity: T): T {
            const initialPath: string = this.path;
            if (!this.path.endsWith('/')) {
                this.path += '/';
            }
            this.path += path;
            const result: T = original(entity);
            this.path = initialPath;
            return result;
        };
    };
}

Upvotes: 1

Related Questions