TypeScript中类型安全的两个同类型对象差异查找方案
我需要对比两个同类型的对象,提取出其中一个对象里不存在于另一个对象,或者属性值不同的所有属性。下面的代码能运行,但存在TypeScript类型错误:
export type Thing = { name?: string; age?: number; location?: { x: number, y: number } }; const things: Thing = { name: "Jim", age: 32, location: {x:1, y:2} }; const things2: Thing = { name: "Jim" }; const things3: Thing = {}; Object.entries(things).forEach(([key, value]) => { if (things[key] !== things2[key]) { things3[key] = value; } });
对应的错误提示:
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Thing'.
No index signature with a parameter of type 'string' was found on type 'Thing'.ts(7053)
我尝试使用ts-extras库的objectEntries方法优化后,错误数量减少:
objectEntries(things).forEach(([key, value]) => { if (things[key] !== things2[key]) { things3[key] = value; } });
但things3[key] = value;这一行仍存在类型错误:
(parameter) key: keyof Thing
Type 'string | number | { x: number; y: number; } | undefined' is not assignable to type 'undefined'.
Type 'string' is not assignable to type 'undefined'.ts(2322)
解决方案
要解决这个问题,核心是让TypeScript明确当前遍历的key对应的value类型与things3中该属性的类型完全匹配。这里提供两种实用方案:
方案一:精准类型断言
直接在赋值时添加类型断言,让TS确认值的类型与目标属性匹配:
objectEntries(things).forEach(([key, value]) => { if (things[key] !== things2[key]) { things3[key] = value as Thing[typeof key]; } });
方案二:封装泛型对比函数
把对比逻辑封装成可复用的泛型函数,从根源上保证类型安全:
function getObjectDiff<T extends object>(objA: T, objB: T): Partial<T> { const diff: Partial<T> = {}; (Object.keys(objA) as Array<keyof T>).forEach(key => { if (objA[key] !== objB[key]) { diff[key] = objA[key]; } }); return diff; } // 使用示例 const things3 = getObjectDiff(things, things2);
注意:上述两种方案都是浅对比,如果对象包含嵌套属性(比如示例中的location),直接用!==只能对比引用地址,无法检测嵌套对象内部值的变化。如果需要深对比,需要额外实现递归对比逻辑。
内容的提问来源于stack exchange,提问作者Evanss

