網站搜尋

裝飾器 - TypeScript 裝飾 setter 函數


我正在嘗試像這樣裝飾一個類的 setter 函數:

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;
    };

 }

使用裝飾器:

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;
   };
}

但是裝飾器從未被呼叫/沒做任何事。
如果我將 @myDeco 放在 getter 函數的上方,裝飾器就會被呼叫並執行它的工作,這非常奇怪……(裝飾的是 setter 函數。)

在 TypeScript 中有可能裝飾 setter 函數嗎?

答案#1

如果你將 getter 和 setter 調換位置,使 setter 先出現——裝飾器就會被調用。

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

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

由於你只能裝飾 setter 或 getter(從不兩者同時),所以宣告的順序很重要。

編輯

對裝飾器放置的限制(無論是在 setter 還是 getter 上)的原因在於 JavaScript 中屬性的定義方式。你的 "sortby" 屬性 getter 和 setter 並不是兩個獨立的屬性。它是一個帶有 getter 和 setter 定義的屬性。裝飾器是附加到屬性的,因此你只能將它附加到屬性一次。無論你用 getter 還是 setter 來應用裝飾器,都沒有關係——生成的 js 代碼將完全相同。通過查看你的範例生成的 js 代碼(稍作簡化),你可以更清楚地理解我的意思:

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;
})();

注意 __decorate 函數是如何被調用的,以及它接受什麼作為輸入。

事實上,TypeScript 編譯器只考慮首先定義的內容(沒有裝飾器的 getter),並忽略應用於同級 setter 的任何裝飾器——這看起來像是一個編譯器錯誤,希望在未來的版本中能夠解決。不過,如果有人更有經驗能證明我錯了,並且這種行為是有原因的,我會非常高興。