In the following code, the only difference between getDocsWithIdThatWorks and getDocsWithIdThatComplains is the callback they are passing to In one case it's a function expression, and in the other it's an overloaded, generic function. In the first case, TypeScript perfectly understands and agrees about the return type of the overloaded function. But when passing the overloaded function's reference directly as an argument to, TypeScript suddenly infers the return type as DocumentWithId<unknown>, despite the fact that the array being mapped is clearly typed as QueryDocumentSnapshot<T>. Why is that so?

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 {

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

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

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


This is a known design limitation of TypeScript; see microsoft/TypeScript#35501. TypeScript can only properly resolve call signatures for overloaded functions when such functions are actually called.

When you write d => withId(d), you are actually calling withId with a parameter of type QueryDocumentSnapshot<T>, and the compiler selects the first call signature, as desired.

But when you just pass withId to map(), you are not calling withId and so the proper overload resolution does not happen. Instead the compiler just "gives up" and picks the last signature. And that results in the error you're seeing.

This happens whenever the compiler has to infer a type involving an overloaded function that it does not call. I don't see direct documentation about this for generic type inference, but it is mentioned in the documentation about conditional type inference, where it says:

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.


node 管道的类型错误 [ERR_INVALID_ARG_TYPE]

无法使用 D3 和 React 在 useEffect 挂钩中进行画笔交互并设置状态


为什么 Array.some() 方法表现不同?

基于 Javascript 中的标签过滤表

带有 redux 工具包的 Redux:UI 没有改变

通过 :even 和 :odd 为 querySelectorAll 提供索引的替代方法

Javascript .createElement & .appendChild 问题(包括 for 和 if)

react 从列表中删除复选框项目,奇怪的行为

如何完全隐藏 Link React 组件?


在 Javascript 中重建/验证 Ruby on Rails Bcrypt 密码哈希

为什么 javascript 渲染已移除的组件

用于大小数字的 Javascript 计数器



react 组件和作为react 组件的功能有什么区别


Typescript :将元组映射到联合类型似乎在嵌套对象中不起作用

C# .NET AES 与 JavaScript 的互操作性