[英]Adding properties to a class via decorators in TypeScript
在 TypeScript 的裝飾器參考頁面上,有一段代碼片段說明了如何使用類裝飾器覆蓋構造函數:
function classDecorator<T extends {new(...args:any[]):{}}>(constructor:T) {
return class extends constructor {
newProperty = "new property";
hello = "override";
}
}
@classDecorator
class Greeter {
property = "property";
hello: string;
constructor(m: string) {
this.hello = m;
}
}
console.log(new Greeter("world"));
並在日志中:
class_1 {
property: 'property',
hello: 'override',
newProperty: 'new property' }
到目前為止,一切都很好。 但是嘗試通過點符號訪問newProperty
失敗:
類型“Greeter”上不存在屬性“newProperty”。ts(2339)
錯誤並且它沒有在 VS Code 的提示中列出。 可以通過括號表示法訪問它,但 TS 警告說
元素隱式具有“任何”類型,因為類型“Greeter”沒有索引簽名。ts(7017)
我錯過了什么嗎? 如何以類型安全的方式通過裝飾器添加新屬性? 我想像普通的類成員一樣擁有普通的編譯器支持。
設計的裝飾器不能改變類的類型。 這仍在討論中,並且在裝飾器提案最終確定之前, 團隊似乎不會改變行為。 你可以使用 mixins 來完成這個任務(閱讀ts 中的 mixins )
使用 mixins 的代碼看起來像:
function classDecorator<T extends { new(...args: any[]): {} }>(constructor: T) {
return class extends constructor {
newProperty = "new property";
hello = "override";
}
}
const Greeter = classDecorator(class {
property = "property";
hello: string;
constructor(m: string) {
this.hello = m;
}
});
type Greeter = InstanceType<typeof Greeter> // have the instance type just as if we were to declare a class
console.log(new Greeter("world").newProperty);
function classDecorator<T extends { new(...args: any[]): {} }>(constructor: T) {
return class extends constructor {
newProperty = "new property";
hello = "override";
}
}
interface classInterface {
newProperty: string;
hello: string;
}
//trick
interface Greeter extends classInterface { };
@classDecorator
class Greeter {
property = "property";
hello: string;
constructor(m: string) {
this.hello = m;
}
}
const b = new Greeter();
console.log(b.newProperty);
看來我們可以使用接口技巧來解決問題。 技巧參考: https ://stackoverflow.com/a/52373394/4831179
我能找到的最佳解決方案是:
export function classDecorator<T extends { new(...args: any[]): {} }>(constructor: T) {
return class extends constructor {
newProperty = "new property";
hello = "override";
}
}
class Greeter {
property = "property";
hello: string;
constructor(m: string) {
this.hello = m;
}
}
注意:這不是最優的,因為它使Greeter.name
返回一個空字符串! 該線程中的其他答案也是如此,所以我仍在尋找解決方案。
不是直接的解決方案,而是避免裝飾器限制的解決方法:在某些情況下,可以將裝飾器替換為可以正確繼承類型的普通類。
class ClassDecorator {
newProperty = "new property";
hello = "override";
}
class Greeter extends ClassDecorator {
property = "property";
hello: string;
constructor(m: string) {
this.hello = m;
}
}
console.log(new Greeter("world"));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.