如果我有一個基類和多個從該基類繼承的子類,例如:
class Message {
constructor(public text: string) {}
}
class MessageA extends Message {
msgType: string = 'A';
constructor(
public text: string,
public aData: string
) {
super(text);
}
}
class MessageB extends Message {
msgType: string = 'B';
constructor(
public text: string,
public bData: number
) {
super(text);
}
}
... 是否可以創建一個只允許子類的型別?
我想要類似的東西
type Msg = MessageA | MessageB;
......這將允許我寫
const show = (msg: Msg): void => {
switch (msg.msgType) {
case 'A':
return console.log(`${msg.text}: ${msg.aData}`);
case 'B':
return console.log(`${msg.text}: ${msg.bData}`);
}
}
但是,上面的代碼給了我這個錯誤:
Property 'aData' does not exist on type 'Msg'.
Property 'aData' does not exist on type 'MessageB'.
如果我將型別更改為以下,則show再次作業:
type Msg = ({msgType: 'A'} & MessageA)
| ({msgType: 'B'} & MessageB);
但如果我再打電話show給一個新的MessageB……
show(new MessageB('hello', 300));
......我得到這個錯誤:
Argument of type 'MessageB' is not assignable to parameter of type 'Msg'.
Type 'MessageB' is not assignable to type '{ msgType: "B"; } & MessageB'.
Type 'MessageB' is not assignable to type '{ msgType: "B"; }'.
Types of property 'msgType' are incompatible.
Type 'string' is not assignable to type '"B"'.(2345)
為基類的子類創建型別的好方法是什么?
這里的目標是確保處理程式在它可以訪問任何欄位(不在基類中)之前檢查它傳遞的物件的型別,并確保switch在將來添加子類時是詳盡的。
uj5u.com熱心網友回復:
看起來你想Msg成為一個有區別的 union,msgType作為一個有區別的屬性。
不幸的是,您已經注釋了msgType屬性 onMessageA和MessageBto be string,并且string不是有效的判別屬性型別。判別式必須是只接受單個值的單位型別,例如undefinedor null,或字串/數字/布爾文字型別。
而不是string,您希望它們分別是字串文字型別"A"和"B"。您可以通過顯式注釋它們或將它們標記為 來做到這一點readonly,這將導致編譯器為它們推斷文字型別:
class MessageA extends Message {
readonly msgType = 'A';
// (property) MessageA.msgType: "A"
constructor(
public text: string,
public aData: string
) {
super(text);
}
}
class MessageB extends Message {
readonly msgType = 'B';
// (property) MessageB.msgType: "B"
constructor(
public text: string,
public bData: number
) {
super(text);
}
}
一旦你這樣做了,你的show()函式的縮小就會起作用:
const show = (msg: Msg): void => {
switch (msg.msgType) {
case 'A':
return console.log(`${msg.text}: ${msg.aData}`); // okay
case 'B':
return console.log(`${msg.text}: ${msg.bData}`); // okay
}
}
Playground 代碼鏈接
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/477941.html
上一篇:將型別物件作為引數傳遞給已鍵入引數的函式是一種很好的做法?
下一篇:檢查一個詞是否是另一個詞的一部分
