我有一個Collection提供基本陣列功能的基類。這個類被擴展用于其他特定領域的用例。當呼叫類似“破壞”的方法時filter,它應該回傳一個帶有過濾元素的新實體(繼續使用類方法而不是僅僅取回陣列)。
在 PHP 中,您可以return new self()根據其構建的基礎來回傳實際的子類或父類(我認為對于 Java,它是return obj.newInstance())。但是對于 JS/TS,我真的很難找到解決方案。我目前的解決方法是newInstance用所有子類覆寫該方法。
有針對這個的解決方法嗎?
class Collection<E> {
protected items: E[];
constructor(items: any[] = []) {
this.items = items;
}
// doesn't work, just one of many attempts
protected newInstance(items: E[]) {
return new Collection(items);
//return new this.constructor(items); // "This expression is not constructable"
// return new this.constructor.prototype(items); // another attempt, says "this.constructor.prototype is not a constructor"
}
size() {
return this.items.length;
}
// should filter and return new instance to use class methods
filter(callback: (item: any, index?: number) => boolean): this {
// should be the actual instance (can be inherited)
return this.newInstance(this.items.filter(callback)) as this;
}
}
class NumberCollection extends Collection<number> {
sum() {
return this.items.reduce((a, b) => a b, 0);
}
}
let numbers = new NumberCollection([1, 2, 3, 4]);
console.log(numbers.sum()); // works,
// throws "sum() is not a function"
console.log(numbers.filter((n) => n > 1).sum());
uj5u.com熱心網友回復:
可悲的是,這是在 JavaScript 中很容易但在 TypeScript 中非常尷尬的事情之一。
在 JavaScript 中,你會做以下兩件事之一:
new this.constructor(/*....*/)正如你提到的。物種格局。
@ts-ignore但不幸的是,如果沒有TypeScript 中的型別斷言或直接的 s,您將無法做到這一點。看到這個關于物種模式的相關問題,答案是:你不能那樣做。
我認為你唯一現實的選擇,如果filter(等等)總是回傳他們被呼叫的類的一個實體(所以它是上面的#1,而不是#2),就是做你所做的this作為回傳型別注釋,new this.constructor(/*...*/)與@ts-ignore它一起使用:
protected newInstance(items: E[]): this {
// @ts-ignore - blech
return new this.constructor(items);
}
游樂場鏈接
這正確地創建了它被呼叫的類的實體(即使 TypeScript 沒有看到構造簽名 on this.constructor),因為默認情況下,分配給類實體的原型具有constructor參考建構式的屬性:this.constructor在通過創建的實體中new Collection是Collection; this.constructor在通過 is 創建的實體new NumberCollection中NumberCollection。(你可以做一些事情來搞砸它,但是class語法可以很容易地避免大多數事情。)所以new this.constructor(/*...*/)使用(在正常情況下)用于創建的建構式創建一個新物件this。結果,您不再有這個sum問題。這有效:
let numbers = new NumberCollection([1, 2, 3, 4]);
console.log(numbers.sum());
const x = numbers.filter((n) => n > 1);
// ^? ?? type is NumberCollection
console.log(x.sum()); // works
我不喜歡它,但據我所知,我們現在堅持下去。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/496814.html
