如何为基于输入类型的返回对象实现严格的TypeScript泛型类型定义
解决TypeScript泛型函数返回类型映射错误的问题
你当前的loadReferencedRecords函数返回类型出现了类型混淆,每个键对应的记录值变成了所有Getter返回类型的联合,核心原因是泛型参数的写法导致类型推导时把所有键的类型混在了一起。以下是修正后的完整实现:
// ---- Example Usage ---- type DataItem = { id1: string; id2: number; data: unknown }; type Type1 = { type1: string }; type Type2 = { type2: string }; const collection: DataItem[] = [ { id1: 'asdfasdf', id2: 123123, data: 'blah' }, { id1: 'zxcvzxcv', id2: 345675647, data: 'zing zang' }, ]; loadReferencedRecords(collection, { id1: (id) => Promise.resolve({ type1: 'asdfas' } as Type1), id2: (id) => Promise.resolve({ type2: 'asdfas' } as Type2), }).then(({ id1: type1sById, // ✅ 类型为 Record<string, Type1> id2: type2sById, // ✅ 类型为 Record<number, Type2> }) => { const type1 = type1sById['asdfasdf']; // ✅ 类型为 Type1 const type2 = type2sById[123123]; // ✅ 类型为 Type2 }); // ---- 修正后的实现 ---- export async function loadReferencedRecords< Item extends Record<string, unknown>, Getters extends Partial<{ [K in keyof Item]: (id: Item[K]) => Promise<unknown> }> >( items: Item[], getters: Getters ): Promise<{ [K in keyof Getters]: Getters[K] extends undefined ? never : Record<Item[K], Awaited<ReturnType<Getters[K]>>> }> { const result: any = {}; // 补充实际业务逻辑:收集ID、批量获取、映射成Record for (const key in getters) { const getter = getters[key]; if (!getter) continue; const ids = items.map(item => item[key]); const records = await Promise.all(ids.map(id => getter(id))); result[key] = Object.fromEntries(ids.map((id, idx) => [id, records[idx]])); } return result; }
关键修改说明
- 移除冗余泛型参数:删掉了
Key extends keyof Getters,直接通过[K in keyof Getters]对每个键单独做类型映射,避免了联合类型混淆。 - 对齐ID类型:将Getter函数的参数类型从固定
string改为Item[K],匹配集合元素对应键的实际类型(比如id2是number,这里就接收number类型参数),类型更严谨。 - 精准推导返回类型:通过
Getters[K] extends undefined ? never : ...排除Partial带来的undefined情况,同时用Awaited<ReturnType<Getters[K]>>单独获取每个Getter返回Promise的解析类型,确保每个键的类型独立不混合。
内容的提问来源于stack exchange,提问作者Carl Napier-Cook
相关产品推荐
相关产品推荐

