如何从泛型对象数组构建TypeScript映射类型?
解决方案
首先,你不能用ObjWithPath<any>[]作为blackBox的参数类型——any会直接丢失每个元素的泛型参数T的类型信息。我们需要让函数接收泛型数组类型,结合TypeScript的映射类型和条件类型来实现需求。
1. 明确ObjWithPath的基础定义
假设你的ObjWithPath是交叉类型实现:
type ObjWithPath<T> = T & { _path: string };
2. 实现blackBox的类型推导
通过泛型数组保留元素的类型细节,再用映射类型将_path转为键、对应泛型参数T转为值:
function blackBox<T extends ObjWithPath<any>[]>( arr: T ): { [K in T[number]['_path']]: Extract<T[number], { _path: K }> extends ObjWithPath<infer U> ? U : never } { // 函数逻辑示例:用reduce聚合为目标结构 return arr.reduce((acc, item) => { acc[item._path] = item; return acc; }, {} as any); }
3. 验证效果
传入具体数组时,返回类型会自动推导为预期的键值对结构:
// 定义带_path的具体对象 const userItem: ObjWithPath<{ name: string; age: number }> = { name: "Josh", age: 30, _path: "user" }; const configItem: ObjWithPath<{ theme: string; autoSave: boolean }> = { theme: "dark", autoSave: true, _path: "config" }; // 返回类型自动推导为:{ user: { name: string; age: number }, config: { theme: string; autoSave: boolean } } const result = blackBox([userItem, configItem]); // 类型校验生效:result.user.age 是number类型,result.config.theme是string类型
关键逻辑说明
T extends ObjWithPath<any>[]:让参数保留每个数组元素的具体类型,避免any抹平类型差异。T[number]['_path']:提取所有元素_path值的联合类型,作为映射类型的键集合。Extract<T[number], { _path: K }>:从元素联合类型中筛选出_path等于当前键K的元素,再通过infer U提取该元素的泛型参数T类型。
内容的提问来源于stack exchange,提问作者Josh
相关产品推荐
相关产品推荐

