簡體   English   中英

當 TypeScript 有多個返回類型時,如何檢查 object 的類型?

[英]How to check the type of an object in TypeScript when it has multiple return type?

我有一個具有多個返回類型的方法。 在這里,一種類型是數組,其余都是單個 object。我想檢查返回類型是否為數組,然后使用循環,否則不使用。

我可以通過使用as來檢測數組類型,但是當我添加if..else條件時,我得到// Getting Property 'forEach' does not exist on type 'output1Model | output2Model | output3Model[]'. Property 'forEach' does not exist on type 'output1Model'. // Getting Property 'forEach' does not exist on type 'output1Model | output2Model | output3Model[]'. Property 'forEach' does not exist on type 'output1Model'. 錯誤。

為什么它以output1Model為目標,即使返回類型指示所有三個?

代碼:

服務.ts

myFunction(input: someModel): output1Model | output2Model | output3Model[] {
    // Some logic. 
   // Return type would be either of these 3 based on condition.
}

controller.ts

const checkThis = Service.myFunction(input);

// ERROR: Getting Property 'forEach' does not exist on type 'output1Model | output2Model | output3Model[]'.
// Property 'forEach' does not exist on type 'output1Model'.
if (checkThis as output3Model[]) {
    checkThis.forEach(element => {
        // DO SOMETHING
    });
} else {
     // DO SOMETHING
}

這里有一些誤解:

  • checkThis as output3Model[]沒有檢測checkThis是否是一個output3Model[] ,它斷言它是一個。 換句話說:您是在告訴編譯器,而不是詢問它。

  • 類型斷言僅影響它們在其中使用的表達式,不會傳播到斷言變量的后續使用。 因此,雖然您可以編寫(checkThis as output3Model[]).forEach(...)來縮小checkThis的感知類型,以便編譯器不會抱怨,但您不能編寫(checkThis as output3Model[])然后稍后再checkThis.forEach() checkThis的第二次使用不是縮小。 如果你想要“檢查並堅持”行為,你需要使用控制流分析 否則,您必須在每次使用checkThis時都斷言。

  • 類型斷言只是與編譯器就您期望看到的類型進行通信的一種方式。 它是 static 類型系統的一部分,因此從發出的 JavaScript 中刪除。上面的代碼最終在 JavaScript 中運行,如下所示:

     if (checkThis) { checkThis.forEach(element => { // DO SOMETHING }); }

    因此,您可以看到您為“檢測” checkThis的類型所做的一切都是為了確保它不是falsy 大概output1Modeloutput2Model是一些對象,因此不是假的,所以這個檢查將始終嘗試運行checkThis.forEach()即使checkThis沒有forEach()方法。 您需要運行時檢查,而不是類型系統工件


所有這一切都意味着編譯器將checkThis視為原始類型output1Model | output2Model | output3Model[] output1Model | output2Model | output3Model[] output1Model | output2Model | output3Model[] ,它抱怨說因為它不確定它有一個forEach()方法,所以嘗試調用它是不安全的。

答案“為什么它以output1Model為目標,即使返回類型指示所有三個?” 與 TypeScript 中錯誤消息的生成方式有關。 如果你有一個類型為A | B | C | D | E | F的值v A | B | C | D | E | F A | B | C | D | E | F並且您嘗試以僅適用於A的方式使用它,編譯器可能會生成一個包含五個錯誤消息的列表,例如“ v可能是一個B ,如果是這樣,您將無法執行您正在做的事情。 “ 和“或者v可能C ,如果是這樣,你就不能做你正在做的事情。” 等等直到“最后, v可能F ,如果是這樣,你就不能做你正在做的事情”。 但實際上,這些錯誤消息中的任何一條都足以告訴您您犯了一個錯誤。 所以它只選擇它遇到的第一個。 v可能是B的事實足以產生關於為什么B不讓你做你想做的事情的警告。


總而言之,您需要使用編譯器可以分析的運行時檢查來驗證您是否將checkThis一個數組,只有當它肯定是一個數組時。 有幾種方法可以做到這一點。

我的建議是Array.isArray() ,其TypeScript 中的類型簽名類型保護 function的類型簽名。 如果Array.isArray(checkThis)在運行時返回true ,那么編譯器知道在控制流中對checkThis的任何后續使用都可以被視為一個數組,因此是一個output3Model[] 如果它返回false ,那么編譯器就知道它不是一個數組,因此必須是一個output1Model | output2Model output1Model | output2Model (假設那些不是數組類型):

if (Array.isArray(checkThis)) {
  checkThis.forEach(element => {
    // (parameter) element: output3Model
  });
} else {
  checkThis
  // const checkThis: output1Model | output2Model
}

游樂場代碼鏈接

我打賭你應該確保你的checkThis是另一種方式的數組,像這樣:

if (Array.isArray(checkThis)) {
    checkThis.forEach(element => {
        // DO SOMETHING
    });
} else {
     // DO SOMETHING
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM