Reputation: 53
I have the following two types and object.
type TypeA = {
a: number;
b: number;
c: number;
};
type TypeB = {
d: number;
e: number;
c: number;
};
oldObject: { [key: string]: TypeA };
I want to map the properties from an object of type TypeA
to an object of type TypeB
. So far I've come up with the following.
const newObject: { [key: string]: TypeB } = {};
Object.entries(oldObject).forEach(([key, value]) => {
newObject[key] = {
d: value.a,
e: value.b,
c: value.c,
} as TypeB;
});
Is there any way of doing this in typescript with something like a map or reduce function? I would much prefer to not have to assign {}
to newObject
at first.
Upvotes: 5
Views: 11089
Reputation: 31833
You can use Object.fromEntries
.
type TypeA = {
a: number;
b: number;
c: number;
};
type TypeB = {
d: number;
e: number;
c: number;
};
declare const oldObject: { [key: string]: TypeA };
const newObject: { [key: string]: TypeB } = Object.fromEntries(
Object.entries(oldObject).map(([key, value]) => [
key,
{
d: value.a,
e: value.b,
c: value.c
}
])
);
To elaborate a little, Object.fromEntries
is, as its name suggests, the inverse of Object.entries
, taking an array of [key, value]
elements and creating an object where the keys are mapped to their corresponding values.
Thus, we start with Object.entries
as before but, instead of using forEach
to populate our new object, we map
over the array, transforming each [key, value]
to [key, newValue]
and pass the resulting array to Object.fromEntries
.
Note that, as jcalz remarks, Object.fromEntries
was introduced in ES2019. If your target runtime does not support ES2019, you will need to add a polyfill such as npm:object.fromentries and correspondingly specify "lib": ["ES2019"]
or higher in your tsconfig.json
I've removed the type assertion as TypeB
since it is both unnecessary and would more importantly would suppress errors like forgetting or misspelling a property declared by TypeB
. Type inference is one of TypeScript's most important aspects.
Your intuition around using map
and reduce
is a very natural one. Not only have we used map
here, but reduce
was frequently used to achieve the same result as Object.fromEntries
before the latter was introduced.
Upvotes: 1
Reputation: 9124
You could also use lodash's mapValue
const oldObject = {
x: { a: 1, b: 2, c: 3 },
y: { a: 11, b: 22, c: 33 },
}
function map(value) {
return {
d: value.a,
e: value.b,
f: value.c
};
}
const newObject = mapValues(oldObject, map);
console.log(newObject);
Upvotes: 0