簡體   English   中英

與 Array.prototype.map 一起使用時,TypeScript 重載泛型函數的返回類型推斷錯誤

[英]TypeScript overloaded generic function's return type inferred incorrectly when used with Array.prototype.map

在以下代碼中, getDocsWithIdThatWorksgetDocsWithIdThatComplains之間的唯一區別是它們傳遞給Array.prototype.map的回調。 在一種情況下,它是一個 function 表達式,而在另一種情況下,它是一個重載的通用 function。 第一種情況,TypeScript完全理解並同意重載的function的返回類型。 但是,當將重載函數的引用直接作為參數傳遞給Array.prototype.map時,TypeScript 突然將返回類型推斷為DocumentWithId<unknown> ,盡管被映射的數組的類型明確為QueryDocumentSnapshot<T> 為什么呢?

游樂場鏈接

interface DocumentSnapshot<T> {
    id: string
    data(): T | undefined
}

interface QueryDocumentSnapshot<T> extends DocumentSnapshot<T> {
    data(): T
}

interface DocumentWithId<T> {
  id: string
  data?: T
}

interface QueryDocumentWithId<T> {
  id: string
  data: T
}


function withId<T>(document: QueryDocumentSnapshot<T>): QueryDocumentWithId<T>
function withId<T>(document: DocumentSnapshot<T>): DocumentWithId<T>
function withId<T>(document: DocumentSnapshot<T> | QueryDocumentSnapshot<T>): DocumentWithId<T> | QueryDocumentWithId<T> {
  return {
    id: document.id,
    data: document.data(),
  }
}

type Query<T> = () => Promise<QueryDocumentSnapshot<T>[]>

async function getDocsWithIdThatWorks<T>(query: Query<T>): Promise<QueryDocumentWithId<T>[]> {
  const result = await query()
  return result.map((d) => withId(d))
}

async function getDocsWithIdThatComplains<T>(query: Query<T>): Promise<QueryDocumentWithId<T>[]> {
  const result = await query()
  return result.map(withId)
}

這是 TypeScript 的已知設計限制; 請參閱microsoft/TypeScript#35501 TypeScript 只有在實際調用重載函數時才能正確解析重載函數的調用簽名。

當您編寫d => withId(d)時,實際上是使用QueryDocumentSnapshot<T>類型的參數調用withId ,編譯器會根據需要選擇第一個調用簽名。

但是,當您只是將withId傳遞給map()時,您並沒有調用withId ,因此不會發生正確的重載解決方案。 相反,編譯器只是“放棄”並選擇最后一個簽名。 這會導致您看到的錯誤。

每當編譯器必須推斷出涉及其未調用的重載 function 的類型時,就會發生這種情況。 我沒有看到有關泛型類型推斷的直接文檔,但在有關條件類型推斷的文檔中提到了它,其中說:

當從具有多個調用簽名的類型(例如重載函數的類型)進行推斷時,會根據最后一個簽名進行推斷(這可能是最寬松的包羅萬象的情況)。 無法根據參數類型列表執行重載決議。

暫無
暫無

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

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