网站搜索

在 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 };