Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

typescript decorate setter function

I'm trying to decorate a setter function, of a class like so:

export class SearchResultSortBy{
    private sortByChoice;
    constructor() { ...} 

     /* getters & setters */
    get sortBy() {
        return this.sortByChoice;
    };

    @myDeco({o:'something',o2:'another something'})
    set sortBy(sortBy) {
        this.sortByChoice = sortBy;
    };

 }

with the decorator:

export function myDeco(element:any){
        return (target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) => {
            descriptor.set = function(...args: any[]) {
                console.log("The method args are: " + JSON.stringify(args)); // pre
                var result = originalMethod.apply(this, args);               // run and store the result
                someOtherStaticClass.someFunc(element);               // post
                return result;                                               // return the result of the original method
            };
        return descriptor;
   };
}

but the decorator is never called/doesn't do anything.
if i place the @myDeco on top of a getter function then the decorator is called and does it's job, which is very odd... (decorates the setter func.)

is it possible to decorate a setter function in typescript?

like image 861
Igoros Avatar asked Jul 04 '26 03:07

Igoros


1 Answers

If you will change places getter and setter in order for the setter to go first - the decorator will be called.

@myDeco({o:'something',o2:'another something'})
set sortBy(sortBy) {
    this.sortByChoice = sortBy;
};

get sortBy() {
    return this.sortByChoice;
};

As you can only decorate setter or getter (never both) it is important what will be declared first.

EDIT

The reason for the restriction on the decorators placement (both on setter and getter) is the way how properties are defined in javascript. Your "sortby" property getter and setter are not two separate properties. It is one property with setter and getter defined. Decorators are attached to properties and therefore you can attach it to property only once. It does not matter getter or setter you will use to apply decorator - the resulting js will be exactly the same. You can more clearly see what I mean by looking at the generated js code for your sample (a bit simplified):

function myDeco(element) {
    return function (target, propertyKey, descriptor) {
        descriptor.set = function () {
            var args = [];
            for (var _i = 0; _i < arguments.length; _i++) {
                args[_i - 0] = arguments[_i];
            }
            return 12; 
        };
        return descriptor;
    };
}
var SearchResultSortBy = (function () {
    function SearchResultSortBy() {
    }
    Object.defineProperty(SearchResultSortBy.prototype, "sortBy", {
        get: function () {
            return this.sortByChoice;
        },
        set: function (sortBy) {
            this.sortByChoice = sortBy;
        },
        enumerable: true,
        configurable: true
    });
    ;
    ;
    __decorate([
        myDeco({ o: 'something', o2: 'another something' }), 
        __metadata('design:type', Object), 
        __metadata('design:paramtypes', [Object])
    ], SearchResultSortBy.prototype, "sortBy", null);
    return SearchResultSortBy;
})();

Note how the __decorate function is called and what it accepts as an input.

The fact that typescript compiler takes into account only what is defined first (getter without decorator) and ignores any decorators applied to the sibling setter - looks like a compiler bug that hopefully will be resolved in the future releases. I would be glad if anyone with more knowledge can prove that I am wrong though and there is a reason for such behavior.

like image 69
Amid Avatar answered Jul 05 '26 18:07

Amid