![](/img/trans.png)
[英]Possible to use Array.prototype.map() on tuple in TypeScript while preserving tuple length in return type?
[英]TypeScript overloaded generic function's return type inferred incorrectly when used with Array.prototype.map
在以下代碼中, getDocsWithIdThatWorks
和getDocsWithIdThatComplains
之間的唯一區別是它們傳遞給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.