TypeScript:为对象数组映射函数定义泛型并消除any类型
TypeScript对象数组键值映射函数消除any类型方案
原代码的核心问题在于泛型设计不合理:ResultType作为外部传入的泛型参数,无法与keyMap、valueMap动态生成的对象结构匹配,加上ObjectType使用any导致类型信息丢失,最终引发类型错误。以下是重构后的解决方案:
重构后的代码
type KeyMap = Map<string, string>; type ValueMap<T> = Map<T, string | number>; export const mapArrayOfObjectsKeysAndValues = <InputType extends Record<string, unknown>>( objectArray: InputType[], keyMap: KeyMap, valueMap: ValueMap<InputType[keyof InputType]> ): Array<{ [K in keyof InputType as K extends string ? (typeof keyMap extends Map<K, infer M> ? M : K) : never]: InputType[K] extends infer V ? (typeof valueMap extends Map<V, infer N> ? N : V) : never }> => { return objectArray.map(object => { const result = {} as { [K in keyof InputType as K extends string ? (typeof keyMap extends Map<K, infer M> ? M : K) : never]: InputType[K] extends infer V ? (typeof valueMap extends Map<V, infer N> ? N : V) : never }; for (const key in object) { if (Object.prototype.hasOwnProperty.call(object, key)) { const originalValue = object[key]; const mappedKey = keyMap.get(key) ?? key; const mappedValue = valueMap.get(originalValue) ?? originalValue; (result as Record<string, unknown>)[mappedKey] = mappedValue; } } return result; }); };
关键修改说明
- 移除不合理泛型参数:删除
ResultType泛型,改为通过keyMap和valueMap的类型自动推导返回值类型,确保返回类型与实际生成的对象结构完全匹配。 - 精准约束输入类型:用
Record<string, unknown>替代ObjectType,避免any导致的类型信息丢失,同时保证输入对象的键为字符串类型。 - 自动推导转换后类型:利用条件类型和
infer关键字,根据keyMap的映射关系推导转换后的键名,根据valueMap推导转换后的值类型。 - 简化逻辑并提升安全性:用空值合并运算符(
??)替代原有的switch分支,添加hasOwnProperty检查避免遍历原型链属性。 - 处理动态赋值类型:临时用
Record<string, unknown>断言完成动态键赋值,绕过TypeScript对动态索引的类型限制,同时保证最终返回类型正确。
类型推导示例
const input = [{ id: 1, name: "Alice" }]; const keyMap = new Map([["id", "userId"]]); const valueMap = new Map([[1, "one"], ["Alice", "ALICE"]]); const result = mapArrayOfObjectsKeysAndValues(input, keyMap, valueMap); // result类型自动推导为:Array<{ userId: string; name: string }>
内容的提问来源于stack exchange,提问作者rseven
相关产品推荐
相关产品推荐

