Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
TypeScript:如何创建类型安全的mapObject函数?_Typescript_Function_Types_Typescript2.0_Type Safety - Fatal编程技术网

TypeScript:如何创建类型安全的mapObject函数?

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

我创建了一个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 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;
    }