ค้นหาเว็บไซต์

วิธีที่ปลอดภัยต่อประเภทในการหาความแตกต่างระหว่างวัตถุ 2 ตัวใน TypeScript?


ฉันมีวัตถุ 2 ชิ้นที่เป็นประเภทเดียวกัน ฉันจำเป็นต้องหาค่าทั้งหมดจากวัตถุหนึ่งที่ไม่มีอยู่ในอีกวัตถุหนึ่ง หรือมีค่าที่แตกต่างกัน

โค้ดนี้ทำงานได้แต่มีข้อผิดพลาดของ 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' ได้ ไม่มีลายเซ็นดัชนีที่มีพารามิเตอร์เป็นชนิด 'string' ถูกพบในชนิด 'Thing'.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 };