TypeScript中Promise.all封装函数丢失可选属性undefined类型问题
优化allPromiseMap函数的类型定义问题
我封装了一个基于Promise.all的函数allPromiseMap,它接收值为Promise的对象,返回键相同、值为对应Promise解析结果的对象。测试时发现一个问题:返回对象的可选属性(比如示例里的world)仍保留可选标记,但把该属性赋值给变量后,类型里的undefined被移除了;而直接定义的同类型对象不会有这个问题。请问该怎么优化函数的类型定义来避免这个问题?
相关代码示例
const allPromiseMap = async <T extends { [KEY in string]: unknown }>(map: { [KEY in keyof T]: Promise<T[KEY]>; }): Promise<T> => { // 函数实现逻辑 const entries = await Promise.all( Object.entries(map).map(async ([key, promise]) => [key, await promise]) ); return Object.fromEntries(entries) as T; }; (async () => { const promises: { hello: Promise<string>; world?: Promise<number>; } = { hello: new Promise(() => { }) } const responseMap = await allPromiseMap(promises); const worldResponse = responseMap.world; // 此处worldResponse的类型被推断为number,而非预期的number | undefined })();
问题原因
原来的泛型约束T extends { [KEY in string]: unknown }会让TypeScript在推断T时,将可选属性的Promise<number>解析为number,但没有正确关联可选属性本身携带的undefined可能性。当访问该属性并赋值给变量时,TypeScript错误地移除了undefined类型分支。
解决方案
修改函数的泛型定义,直接基于输入的Promise对象类型进行映射,明确保留可选属性的undefined类型:
// 定义工具类型,提取Promise的解析值类型 type ResolvePromise<T> = T extends Promise<infer U> ? U : never; // 辅助类型,定义函数返回值类型 type PromiseReturnType<P> = { [K in keyof P]: P[K] extends Promise<infer U> ? U : undefined; }; const allPromiseMap = async <P extends Record<string, Promise<unknown> | undefined>>( map: P ): Promise<PromiseReturnType<P>> => { const entries = await Promise.all( Object.entries(map).map(async ([key, promise]) => [ key, // 处理可选属性可能为undefined的情况 promise instanceof Promise ? await promise : undefined ]) ); return Object.fromEntries(entries) as PromiseReturnType<P>; };
测试验证
修改后,重新测试代码:
(async () => { const promises: { hello: Promise<string>; world?: Promise<number>; } = { hello: new Promise(resolve => resolve("hi")) } const responseMap = await allPromiseMap(promises); const worldResponse = responseMap.world; // 此时worldResponse的类型为number | undefined,符合预期 })();
这样修改后,返回对象的可选属性赋值给变量时,undefined类型会被正确保留,与直接定义同类型对象的行为一致。
内容的提问来源于stack exchange,提问作者Sandy Gifford
相关产品推荐
相关产品推荐

