如何修正TypeScript中对象指定字段转数字的类型报错?
实现指定字段字符串转数字的TypeScript类型安全函数
我需要编写一个函数,将对象中指定字段的字符串值转换为数字,目前写了两个版本但都存在类型问题:
第一个函数版本
export function convertStringToNumber<K extends string>( obj: Record<K, object>, val: string ): Record<K, number> { const result: Partial<Record<K, unknown>> = {} for (const key in obj) { if (key === val) { result[key] = Number(obj[key]) } else { result[key] = obj[key] } } return result as Record<K, number> }
这个函数能正常运行,但TypeScript有类型报错,我希望TypeScript能根据输入类型,仅将指定键的类型改为数字,而不是把所有键都设为number类型。
第二个函数版本
export function convertStringToNumber2<T> ( obj: T, val: string ): T { const result: Partial<T> = {} for (const key in obj) { if (key === val) { result[key] = Number(obj[key]) } else { result[key] = obj[key] } } return result }
此时TypeScript报错:Type 'number' is not assignable to type 'T[Extract<keyof T, string>]'.ts(2322),请问该如何解决?
解决方案
要实现类型安全的转换,需要利用TypeScript的映射类型和条件类型,精准修改指定键的类型:
export function convertStringToNumber<T, K extends keyof T>( obj: T, key: K ): Omit<T, K> & Record<K, number> { const result = { ...obj }; result[key] = Number(obj[key]) as T[K] & number; return result as Omit<T, K> & Record<K, number>; }
类型说明
- 泛型参数:
T:接收输入对象的完整类型K:限制为T的键类型,确保传入的key是对象已存在的属性
- 返回类型:
Omit<T, K> & Record<K, number>Omit<T, K>:保留原对象除K之外的所有属性类型Record<K, number>:将指定键K的类型改为number- 两者交叉后,得到仅修改指定键类型的新对象类型
- 实现细节:
- 拷贝原对象避免修改源数据
- 用
Number()转换值,通过类型断言解决赋值时的类型冲突 - 最后将结果断言为目标交叉类型
使用示例
const user = { name: "Alice", age: "25", score: "90" }; const convertedUser = convertStringToNumber(user, "age"); // convertedUser 类型为:{ name: string; score: string; } & { age: number; } console.log(convertedUser.age); // 25(类型为number)
第二个版本报错的核心原因
第二个版本返回原类型T,但T中指定键的类型原本是string,转换后赋值为number必然不符合原类型约束。通过返回修改后的交叉类型而非原类型T,即可解决类型不匹配问题。
内容的提问来源于stack exchange,提问作者Giuseppe Bosco
相关产品推荐
相关产品推荐

