Если вы используете для l oop вместо reduce
, тогда TypeScript сможет правильно отследить тип переменной итератора i
.
В противном случае, как указал Псидом, Object.keys()
возвращает string[]
, что приводит к потере свойства: сопоставление значений.
Вот минимально измененная версия вашего кода:
type ValueOf<T> = T[keyof T];
export const mapObject = <OldObject extends object, NewValue>(
mappingFn: (value: ValueOf<OldObject>) => NewValue,
obj: OldObject
): Record<keyof OldObject, NewValue> => {
let newObj = {} as Record<keyof OldObject, NewValue>;
for (let i in obj) {
if (obj.hasOwnProperty(i)) {
const oldValue = obj[i];
newObj[i] = mappingFn(oldValue);
}
}
return newObj;
}
Но есть несколько различных способов аннотировать его Для достижения того же результата семантика немного различается.
Вот альтернативная версия, использующая сопоставленные типы (выглядит аналогично, но это не сигнатура индекса).
Это может быть немного более гибкий, потому что входному объекту не нужно , чтобы был типом Record
со значениями того же типа.
Реализация такая же, это просто аннотации типов, которые разные:
type ValueOf<T> = T[keyof T];
type MapTo<T, U> = {
[P in keyof T]: U
}
function mapObject<T extends object, U>(mappingFn: (v: ValueOf<T>) => U, obj: T): MapTo<T, U> {
let newObj = {} as MapTo<T, U>;
for (let i in obj) {
if (obj.hasOwnProperty(i)) {
const oldValue = obj[i];
newObj[i] = mappingFn(oldValue);
}
}
return newObj;
}