如何为TypeScript合并键值对的函数正确标注类型
解决TypeScript合并对象键值对的类型标注问题
你当前的代码返回类型用了字符串索引签名,所以不管写newKey还是newKey2都不会触发错误——因为TypeScript把[newKey: string]当成任意字符串键的索引,而非绑定到参数newKey的具体字面量。要实现严格的键名约束,需用泛型字面量类型锁定newKey,同时正确处理原键删除与新键添加的类型逻辑:
修正后的代码实现
function mergeKeyValues<T, K extends string, S>( obj: T, key1: keyof T, key2: keyof T, newKey: K, mergeFn: (a: T[typeof key1], b: T[typeof key2]) => S ): Omit<T, typeof key1 | typeof key2> & { [P in K]: S } { // 过滤待删除的键,构造新对象 const filteredEntries = Object.entries(obj).filter( ([key]) => key !== key1 && key !== key2 ); const mergedValue = mergeFn(obj[key1], obj[key2]); return { ...Object.fromEntries(filteredEntries), [newKey]: mergedValue } as Omit<T, typeof key1 | typeof key2> & { [P in K]: S }; }
关键改进说明
- 泛型锁定新键名:新增泛型
K extends string,将newKey约束为具体字符串字面量(比如传入"fullName"时,K就是"fullName"),返回类型中的{ [P in K]: S }会严格对应这个字面量键,修改键名会直接触发类型错误。 - 精确的合并函数参数类型:把
mergeFn的参数从T[keyof T]改为T[typeof key1]和T[typeof key2],确保传入的两个值类型与原对象对应键的类型完全匹配。 - 正确移除原键的类型:用
Omit<T, typeof key1 | typeof key2>从原类型中剔除key1和key2,再与新键类型交叉,保证返回类型不含原键且包含指定新键。
测试示例
const user = { firstName: "John", lastName: "Doe", age: 30 }; const mergedUser = mergeKeyValues( user, "firstName", "lastName", "fullName", (a, b) => `${a} ${b}` ); // mergedUser 的类型为:Omit<typeof user, "firstName" | "lastName"> & { fullName: string } // 即 { age: number; fullName: string } console.log(mergedUser.fullName); // "John Doe" console.log(mergedUser.firstName); // 类型报错(原键已被删除)
内容的提问来源于stack exchange,提问作者Willem Vanhulle
相关产品推荐
相关产品推荐

