I am currently working on creating a function in Typescript
that will map an object while ensuring that it retains the same keys. I have attempted different methods, but none seem to work as intended:
function mapObject1<K extends PropertyKey, A, B>(
object: { [P in K]: A },
mapper: (value: A) => B,
): { [P in K]: B } {
return Object.fromEntries(
Object.entries(object)
.map(([key, value]): [K, B] => [key, mapper(value)]),
); // error!
// Type '{ [k: string]: B; }' is not assignable to type '{ [P in K]: B; }'
}
export function mapObject2<K extends PropertyKey, A, B>(
object: { [P in K]: A },
mapper: (value: A) => B,
): { [P in K]: B } {
const result: { [P in K]?: B } = {};
(Object.keys(object) as K[]).forEach((key: K) => {
result[key] = mapper(object[key]);
});
return result; // error!
// Type '{ [P in K]?: B | undefined; }' is not assignable to type '{ [P in K]: B; }'
}
In mapObject1
, when using Object.entries()
and Object.fromEntries()
, the key types are converted to string
. In mapObject2
, since result
's keys start out empty, they must be optional, leading Typescript
to fail recognizing all original keys from object
. How can this issue be resolved?