วิธีที่ปลอดภัยต่อประเภทในการหาความแตกต่างระหว่างวัตถุ 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 };
