gpt4 book ai didi

javascript - TypeScript 重载泛型函数的返回类型在与 Array.prototype.map 一起使用时被错误推断

转载 作者:行者123 更新时间:2023-12-05 02:27:23 25 4
gpt4 key购买 nike

在下面的代码中,getDocsWithIdThatWorks之间的唯一区别是和 getDocsWithIdThatComplains是他们传递给 Array.prototype.map 的回调.在一种情况下它是一个函数表达式,而在另一种情况下它是一个重载的泛型函数。在第一种情况下,TypeScript 完全理解并同意重载函数的返回类型。但是当将重载函数的引用直接作为参数传递给 Array.prototype.map 时, TypeScript 突然将返回类型推断为 DocumentWithId<unknown> ,尽管被映射的数组明确键入为 QueryDocumentSnapshot<T> .为什么会这样?

Playground link

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 只能正确解析 overloaded functions 的调用签名当实际调用此类函数时。

当你写 d => withId(d) , 你实际上是在调用 withId参数类型为 QueryDocumentSnapshot<T> , 编译器根据需要选择第一个调用签名。

但是当你刚刚通过 withIdmap() , 你没有调用 withId因此不会发生正确的重载决议。相反,编译器只是“放弃”并选择最后一个签名。这会导致您看到的错误。

每当编译器必须推断涉及它不调用的重载函数的类型时,就会发生这种情况。我没有看到有关通用 类型推断的直接文档,但在 documentation about conditional type inference 中提到了它,它说:

When inferring from a type with multiple call signatures (such as the type of an overloaded function), inferences are made from the last signature (which, presumably, is the most permissive catch-all case). It is not possible to perform overload resolution based on a list of argument types.

关于javascript - TypeScript 重载泛型函数的返回类型在与 Array.prototype.map 一起使用时被错误推断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73252877/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com