TypeScript如何基于RecursivePartial实现嵌套对象深度更新
递归深度更新对象实现方案
第一步:定义支持嵌套和数组的RecursivePartial类型
原始的RecursivePartial未适配数组结构,修改后可兼容数组、多层嵌套对象场景:
export type RecursivePartial<T> = { [P in keyof T]?: T[P] extends (infer U)[] ? RecursivePartial<U>[] : T[P] extends object ? RecursivePartial<T[P]> : T[P]; };
第二步:实现深度合并函数
函数会递归遍历所有层级的属性,仅覆盖更新对象中存在的字段,其余原值保留,同时适配数组类型的合并:
export function updateFromPartial<T>(obj: T, updates: RecursivePartial<T>): T { // 基础类型、null的场景直接返回更新值 if (updates === null || typeof updates !== 'object') { return updates as T; } // 数组场景按索引合并对应项 if (Array.isArray(obj) && Array.isArray(updates)) { return updates.map((updateItem, index) => updateFromPartial(obj[index], updateItem) ) as unknown as T; } // 普通对象场景递归合并每个属性 const merged = {...obj}; for (const key in updates) { if (Object.prototype.hasOwnProperty.call(updates, key)) { merged[key] = updateFromPartial( obj[key], updates[key] as RecursivePartial<typeof obj[key]> ); } } return merged; }
使用示例
以你定义的SalesOrder接口为例,效果如下:
export interface SalesOrder { id: number, DeliveryInfo: { Address: { province: string, city: string }, DeliveryTime: string }, items: {id: number, name: string, count: number}[] } // 原始对象 const originalOrder: SalesOrder = { id: 1, DeliveryInfo: { Address: { province: '广东', city: '深圳' }, DeliveryTime: '2024-01-01' }, items: [ {id: 1, name: '商品1', count: 2}, {id: 2, name: '商品2', count: 3} ] }; // 仅更新指定嵌套字段,其余字段自动保留 const updatedOrder = updateFromPartial(originalOrder, { DeliveryInfo: { DeliveryTime: '2024-02-01' }, items: [ {count: 5} ] }); // 输出验证 console.log(updatedOrder.DeliveryInfo.Address.province); // 广东 原值保留 console.log(updatedOrder.DeliveryInfo.DeliveryTime); // 2024-02-01 字段更新成功 console.log(updatedOrder.items[0].count); // 5 数组成员字段更新成功 console.log(updatedOrder.items[0].name); // 商品1 数组成员其余字段保留
可选调整说明
- 如果需要跳过值为
undefined的更新字段,可在对象属性遍历逻辑中增加if (updates[key] === undefined) continue判断 - 如果数组需要按业务ID匹配而非索引匹配合并,可修改数组处理逻辑,遍历更新数组的元素,按ID找到原数组对应项再合并
内容的提问来源于stack exchange,提问作者chxpel
相关产品推荐
相关产品推荐

