Reputation: 23142
I have 2 objects of the same type. I need to find all of the values from one object that either don't exist in the other, or have a different value.
This code works but has TypeScript errors:
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)
Ive reduced the number of errors by using the ts-extras
library:
objectEntries(things).forEach(([key, value]) => {
if (things[key] !== things2[key]) {
things3[key] = value;
}
});
But I still get this error by 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)
Upvotes: 3
Views: 730
Reputation: 147
You could make use of Partial Types:
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>
makes all properties optional while keeping type safety. You can then cast key
as keyof Thing
to ensure validity. As well as value
as Thing[keyof Thing]
so TS knows it exists in Thing
.
Your result should be this:
{ age: 32, location: { x: 1, y: 2 } }
Upvotes: 0
Reputation: 4282
Add an intersection to explicitly require keys of Thing to be string:
type Thing = {
name?: string;
age?: number;
location?: {
x: number,
y: number
}
} & { [key: string]: any };
Upvotes: -1