裝飾器 - 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 的任何裝飾器——這看起來像是一個編譯器錯誤,希望在未來的版本中能夠解決。不過,如果有人更有經驗能證明我錯了,並且這種行為是有原因的,我會非常高興。
