You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Object.fromEntries处理请求数据时的TypeScript报错问题

问题

我有一个结构为{ name: url, name: url, ...}的requests对象,想要请求每个url并返回{ name: data, name: data, ...}的结构。编写对应的TypeScript代码后,在使用Object.fromEntries处理Promise.all返回的results时出现TS2769类型错误,目前仅能通过将results设为any[]解决,希望找到正确的类型处理方案。

代码示例

async function fetchMovies(url: string) {
  const data = await fetch(baseURL + url).then((r) => r.json());
  return data.results;
}

export const getMovies = createAsyncThunk("movies/getMovies", async () => {
  const responses = Object.entries(requests).map(async ([key, value]) => {
    try {
      const response = await fetchMovies(value);
      return [key, response];
    } catch (e: unknown) {
      if (e instanceof Error) {
        console.log(e.message);
      }
    }
  });

  const results = await Promise.all(responses);
  console.log(results); // [[string, SomeType[]], [string, SomeType[]], ...]
  return Object.fromEntries(results); // error
});

console.log(results)输出

Array (8)
 0 ["netflixOriginals", Array] (2)
 1 ["trending", Array] (2)
 2 ["topRated", Array] (2)
 3 ["action", Array] (2)
 4 ["comedy", Array] (2)
 5 ["horror", Array] (2)
 6 ["romance", Array] (2)
 7 Array (2)
   0 "documentary"
   1 [Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, …] (20)

错误信息

TS2769: 没有匹配的重载调用。
  重载1/2, '(entries: Iterable<readonly [PropertyKey, any]>): { [k: string]: any; }', 给出以下错误。
    参数类型'(any[] | undefined)[]'不能赋值给类型'Iterable<readonly [PropertyKey, any]>'。
      '[Symbol.iterator]().next(...)'返回的类型在这两个类型之间不兼容。
        类型'IteratorResult<any[] | undefined, any>'不能赋值给类型'IteratorResult<readonly [PropertyKey, any], any>'。
          类型'IteratorYieldResult<any[] | undefined>'不能赋值给类型'IteratorResult<readonly [PropertyKey, any], any>'。
            类型'IteratorYieldResult<any[] | undefined>'不能赋值给类型'IteratorYieldResult<readonly [PropertyKey, any]>'。
              类型'any[] | undefined'不能赋值给类型'readonly [PropertyKey, any]'。
                类型'undefined'不能赋值给类型'readonly [PropertyKey, any]'。
  重载2/2, '(entries: Iterable<readonly any[]>): any', 给出以下错误。
    参数类型'(any[] | undefined)[]'不能赋值给类型'Iterable<readonly any[]>'。
      '[Symbol.iterator]().next(...)'返回的类型在这两个类型之间不兼容。
        类型'IteratorResult<any[] | undefined, any>'不能赋值给类型'IteratorResult<readonly any[], any>'。
          类型'IteratorYieldResult<any[] | undefined>'不能赋值给类型'IteratorResult<readonly any[], any>'。
            类型'IteratorYieldResult<any[] | undefined>'不能赋值给类型'IteratorYieldResult<readonly any[]>'。
              类型'any[] | undefined'不能赋值给类型'readonly any[]'。
                类型'undefined'不能赋值给类型'readonly any[]'。
    22 |   const results = await Promise.all(responses);
    23 |   console.log(results);
  > 24 |   return Object.fromEntries(results);
       |                             ^^^^^^^
    25 | });
    26 |
解决方案

1. 消除undefined类型隐患

错误核心是map中的异步函数在catch分支没有返回值,导致每个Promise的返回类型为[string, SomeType[]] | undefined,最终results类型变成([string, SomeType[]] | undefined)[],而Object.fromEntries不接受包含undefined的数组。

方案A:给catch分支设置默认返回值

const responses = Object.entries(requests).map(async ([key, value]) => {
  try {
    const response = await fetchMovies(value);
    return [key, response] as const; // 用as const固定元组类型,避免被推断为松散数组
  } catch (e: unknown) {
    if (e instanceof Error) {
      console.log(e.message);
    }
    return [key, []] as const; // 返回空数组作为默认数据,保证类型统一
  }
});

方案B:过滤掉数组中的undefined项

const results = await Promise.all(responses);
// 类型守卫:明确过滤后的数据类型
const validResults = results.filter((entry): entry is [string, SomeType[]] => entry !== undefined);
return Object.fromEntries(validResults);

2. 给fetchMovies添加明确类型定义

当前fetchMovies返回any类型,需要定义数据接口让TypeScript正确推断类型:

// 定义电影数据的具体结构
interface Movie {
  id: number;
  title: string;
  poster_path: string;
  // 其他字段根据实际接口补充
}

async function fetchMovies(url: string): Promise<Movie[]> {
  const res = await fetch(baseURL + url);
  // 增加请求失败的错误抛出,避免后续处理异常数据
  if (!res.ok) throw new Error(`请求失败:${res.status}`);
  const data = await res.json();
  return data.results as Movie[]; // 断言为Movie数组,或根据接口文档做更严格的类型校验
}

3. 固定返回值的元组类型

在返回键值对时用as const,让TypeScript将其推断为只读元组readonly [string, Movie[]],而非松散的any[],提升类型精度:

const responses = Object.entries(requests).map(async ([key, value]) => {
  try {
    const response = await fetchMovies(value);
    return [key, response] as const;
  } catch (e: unknown) {
    if (e instanceof Error) {
      console.log(e.message);
    }
    return [key, []] as const;
  }
});

4. 明确最终返回值类型

如果需要让getMovies的返回类型更清晰,可以手动定义对应类型:

// 根据requests的键生成返回对象的类型
type MoviesResponse = {
  [K in keyof typeof requests]: Movie[];
};

// 给createAsyncThunk指定泛型参数,明确输入输出类型
export const getMovies = createAsyncThunk<MoviesResponse, void>(
  "movies/getMovies", 
  async () => {
    const responses = Object.entries(requests).map(async ([key, value]) => {
      try {
        const response = await fetchMovies(value);
        return [key, response] as const;
      } catch (e: unknown) {
        if (e instanceof Error) console.log(e.message);
        return [key, []] as const;
      }
    });

    const results = await Promise.all(responses);
    return Object.fromEntries(results) as MoviesResponse;
  }
);

内容的提问来源于stack exchange,提问作者cheech

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 07:15:34