我使用以下 Typescript 類:
我有一個抽象類
export abstract class MyAbstractClass { ..... }實作抽象類方法的A類
export ClassA extends MyAbstractClass { readonly MY_FIRST_CONTS = 'blaa'; readonly MY_SECOND_CONTS = 'blaablaaa'; .... }B 類擴展了 A 類,我想覆寫 MY_FIRST_CONTS 值。沒有設定其他實作
export ClassB extends ClassA { readonly MY_FIRST_CONTS = 'other blaa'; readonly MY_SECOND_CONTS = 'other blaablaaa'; .... }
我經常在 ClassB 中的 MY_FIRST_CONST 行收到以下錯誤:
Property 'MY_FIRST_CONST' in type 'ClassB' is not assignable to the same property in base type 'ClassA'.
型別 '"other blaa"' 不能分配給型別 '"blaa"'。
我不明白為什么會出現此錯誤,更不明白為什么 MY_SECOND_CONST 不會發生此錯誤。
有任何想法嗎?非常感謝!
uj5u.com熱心網友回復:
你有一個設計問題。技術問題來自這樣一個事實,即您正在覆寫readonly子類中的屬性,這沒有意義。
要么您希望子類能夠更改該值,那么它不應該是readonly. 或者您不希望子類能夠更改值,那么您不能在子類中宣告不同的值。
但是,您可能還希望子類能夠定義實體化后無法更改的值。這可以使用適當的建構式或 getter 來完成:
使用建構式:
export class ClassA extends MyAbstractClass {
readonly foo;
constructor(foo = 'foo') {
super();
this.foo = foo;
}
}
export class B extends ClassA {
constructor() {
super('bar')
}
}
使用吸氣劑:
export class ClassA extends MyAbstractClass {
get foo() {
return 'foo';
}
}
export class B extends ClassA {
get foo() {
return 'bar';
}
}
uj5u.com熱心網友回復:
為了回答這個問題,我們需要看看編譯器是如何在 JS 中參考這一切的:
"use strict";
class AbstractClass {
}
class ClassA extends AbstractClass {
constructor() {
super(...arguments);
this.MY_FIRST_CONTS = 'blaa';
this.MY_SECOND_CONTS = 'blaablaaa';
}
}
class ClassB extends ClassA {
constructor() {
super(...arguments);
this.MY_FIRST_CONTS = 'other blaa';
this.MY_SECOND_CONTS = 'other blaablaaa';
}
}
這很容易說,同一個變數被宣告了兩次,Typescript 給你一個錯誤,因為你在ClassAas中宣告了變數readonly。
如果您仍然需要這兩個變數ClassA,ClassB您可以將變數宣告ClassA為嚴格私有的。
export ClassA extends MyAbstractClass {
#MY_FIRST_CONTS = 'blaa';
#MY_SECOND_CONTS = 'blaablaaa';
....
}
ClassA現在您可能會考慮使用 a訪問變數get,但出于同樣的原因,這會引發另一個錯誤。
export class ClassA extends AbstractClass {
#MY_FIRST_CONTS = 'blaa';
#MY_SECOND_CONTS = 'blaablaaa';
get MY_FIRST_CONTS() { return this.#MY_FIRST_CONTS}
get MY_SECOND_CONTS() { return this.#MY_SECOND_CONTS}
}
export class ClassB extends ClassA {
//'MY_FIRST_CONTS' is defined as an accessor in class 'ClassA', but is overridden here in 'ClassB' as an instance property.
readonly MY_FIRST_CONTS = 'other blaa';
//'MY_SECOND_CONTS' is defined as an accessor in class 'ClassA', but is overridden here in 'ClassB' as an instance property.
readonly MY_SECOND_CONTS = 'other blaablaaa';
}
因此,要使其正常作業,您必須將變數包裝在一個get方法中,然后覆寫以下get方法ClassB:
export abstract class AbstractClass {
}
export class ClassA extends AbstractClass {
#MY_FIRST_CONTS = 'blaa';
#MY_SECOND_CONTS = 'blaablaaa';
get MY_FIRST_CONTS() { return this.#MY_FIRST_CONTS}
get MY_SECOND_CONTS() { return this.#MY_SECOND_CONTS}
}
export class ClassB extends ClassA {
#MY_FIRST_CONTS = 'other blaa';
#MY_SECOND_CONTS = 'other blaablaaa';
override get MY_FIRST_CONTS() {return this.#MY_FIRST_CONTS}
override get MY_SECOND_CONTS() {return this.#MY_SECOND_CONTS}
}
uj5u.com熱心網友回復:
鑒于特定的錯誤訊息,問題實際上是編譯器將您的 A 類屬性解釋為被鍵入為特定字串而不是string本身,并且錯誤訊息告訴您新的“字串”與唯一的字串值不兼容允許。
如果您將滑鼠懸停在MY_FIRST_CONTS屬性上并查看 TypeScript 認為該型別是什么(不是string但是blaa!),您可以看到這一點。
如果我們顯式鍵入MY_FIRST_CONTSand MY_SECOND_CONTSas string,則沒有其他問題。
export abstract class MyAbstractClass {
}
class ClassA extends MyAbstractClass {
readonly MY_FIRST_CONTS: string = 'blaa';
readonly MY_SECOND_CONTS: string = 'blaablaaa';
}
class ClassB extends ClassA {
readonly MY_FIRST_CONTS = 'other blaa';
readonly MY_SECOND_CONTS = 'other blaablaaa';
}
打字稿游樂場
uj5u.com熱心網友回復:
根據您的 Typescript 版本,您是否嘗試指定它是 override ?
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html
export class ClassB extends ClassA {
override MY_FIRST_CONTS = 'blaa';
override MY_SECOND_CONTS = 'blaablaaa';
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/445933.html
