使用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
相关产品推荐
相关产品推荐

