TypeScript:如何创建类型安全的mapObject函数?
我创建了一个util函数mapObject,它是Array.map,但用于对象 它是这样使用的TypeScript:如何创建类型安全的mapObject函数?,typescript,function,types,typescript2.0,type-safety,Typescript,Function,Types,Typescript2.0,Type Safety,我创建了一个util函数mapObject,它是Array.map,但用于对象 它是这样使用的 mapObject( (value) => value * 100, {a: 1, b: 2, c: 3} ) // {a: 100, b: 200, c: 300} 下面是实现。我得到了一个很好的类型安全版本,但是在没有索引签名的情况下使用obj[key]时,不得不消除两个错误 type ValueOf<T> = T[keyof T]; export const map
mapObject(
(value) => value * 100,
{a: 1, b: 2, c: 3}
)
// {a: 100, b: 200, c: 300}
下面是实现。我得到了一个很好的类型安全版本,但是在没有索引签名的情况下使用obj[key]时,不得不消除两个错误
type ValueOf<T> = T[keyof T];
export const mapObject = <OldObject, NewValue>(
mappingFn: (value: ValueOf<OldObject>) => NewValue,
obj: OldObject
): Record<keyof OldObject, NewValue> =>
Object.keys(obj).reduce((newObj, key) => {
// @ts-ignore (Not sure how to work around this)
const oldValue = obj[key];
// @ts-ignore (Not sure how to work around this)
newObj[key] = mappingFn(oldValue);
return newObj;
}, {} as Record<keyof OldObject, NewValue>);
有什么更好的编码方法?该函数正确地推断传入的内容,返回值具有很强的类型安全性。我希望删除@ts忽略,但不使用索引签名,因为它们会损害类型安全。Object.keys返回字符串[]。一种可能的解决方案是对Object.keys使用类型断言,如中所述:
.Object.keys返回字符串[]。一种可能的解决方案是对Object.keys使用类型断言,如中所述:
.如果使用for循环而不是reduce,则TypeScript能够正确跟踪i迭代器变量的类型 否则,正如Psidom指出的那样,Object.keys返回字符串[],该字符串将丢失属性:值映射 以下是代码的最小更改版本:
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;
}
如果使用for循环而不是reduce,那么TypeScript能够正确跟踪i迭代器变量的类型 否则,正如Psidom指出的那样,Object.keys返回字符串[],该字符串将丢失属性:值映射 以下是代码的最小更改版本:
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;
}
为什么索引签名会损害类型安全?如果要处理具有任意多个属性的对象,据我所知,无法绕过它们。@philmcole,因为用户现在可以访问返回对象上不存在的键。在转换obj的同时尽我最大的努力维护它的安全性。为什么索引签名会损害类型安全性?如果要处理具有任意多个属性的对象,据我所知,无法绕过它们。@philmcole,因为用户现在可以访问返回对象上不存在的键。在改造obj的同时,尽我最大的努力维护它的安全。第一个答案是按照我的需要工作,不再需要@ts忽略!非常感谢。第一个答案是我所需要的,不再需要@ts ignore了!非常感谢你。
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;
}