如何为TypeScript对象转换函数正确声明输入输出类型关系?
解决TypeScript对象类型转换的类型不兼容问题
修正后的代码方案
首先调整类型定义,让输出类型精准映射输入属性的类型,同时保留可选性:
// 输入类型:属性为 string | undefined 的对象,支持可选属性 type InputObject = Record<string, string | undefined>; // 输出类型:对每个属性做类型转换,保留原属性的可选性 type TransformedObject<T extends InputObject> = { [K in keyof T]: T[K] extends string ? number : number | undefined; }; function transformObject<T extends InputObject>(input: T): TransformedObject<T> { const result = {} as TransformedObject<T>; for (const key in input) { const value = input[key]; // 针对当前key做精确类型断言,解决循环中的类型推断问题 result[key] = (value === undefined ? undefined : value.length) as TransformedObject<T>[typeof key]; } return result; } // 测试用例 const obj = { background: 'red', color: 'blue', border: undefined }; const obj2 = transformObject(obj); const bgLength: number = obj2.background; // 类型匹配,无报错 const borderLength: number | undefined = obj2.border; // 类型匹配,无报错
问题根源说明
你之前的代码里,Out<T>的条件类型T[K] extends undefined ? number | undefined : number存在逻辑缺陷:当输入属性是string | undefined这种联合类型时,TypeScript的条件类型会触发联合类型分发,导致最终类型虽然正确,但在循环遍历对象属性时,TypeScript无法推断出当前key对应的具体分支类型,所以会抛出number | undefined无法赋值给对应条件类型的错误。
另外,原代码里的T extends In<T>泛型约束属于冗余写法,直接约束T为Record<string, string | undefined>更清晰直观。
通过给result[key]的赋值加上as TransformedObject<T>[typeof key]的精确断言,我们明确告诉TypeScript当前key对应的输出类型就是该位置应该的类型,既解决了类型不兼容问题,又完整保留了原对象的属性可选性。
内容的提问来源于stack exchange,提问作者Robert Kajic
相关产品推荐
相关产品推荐

