在 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;
}
});
元素隐式具有“any”类型,因为类型为“string”的表达式不能用于索引类型“Thing”。在类型“Thing”上未找到参数类型为“string”的索引签名。ts(7053)
我通过使用 ts-extras 库减少了错误数量:
objectEntries(things).forEach(([key, value]) => {
if (things[key] !== things2[key]) {
things3[key] = value;
}
});
但是我仍然在使用 things3[key]=value; 时遇到这个错误:
(参数) key: keyof Thing 类型 'string | number | { x: number; y: number; } | undefined' 不能赋值给类型 'undefined'。类型 'string' 不能赋值给类型 'undefined'。ts(2322)
答案#1
你可以使用部分类型:
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 = {} as Partial<Record<keyof Thing, any>>;
Object.entries(things).forEach(([key, value]) => {
const thingKey = key as keyof Thing;
if (things[thingKey] !== things2[thingKey]) {
things3[thingKey] = value as Thing[keyof Thing];
}
});
Partial<Thing> 使所有属性变为可选,同时保持类型安全。然后你可以将 key 强制转换为 keyof Thing 来确保有效性。同时将 value 转换为 Thing[keyof Thing],这样 TS 就知道它存在于 Thing 中。
你的结果应该是这个:
{ age: 32, location: { x: 1, y: 2 } }
答案#2
添加一个交叉类型以明确要求 Thing 的键为字符串:
type Thing = {
name?: string;
age?: number;
location?: {
x: number,
y: number
}
} & { [key: string]: any };
