如何为TypeScript中fooFunc函数推导目标返回值类型?
如何在TypeScript中定义基于数组元素属性的函数返回类型
要实现你需要的返回类型,得利用TypeScript的类型编程提取数组中每个元素的键值对类型并合并,同时确保TypeScript能推断出具体的键名和值类型(而非宽泛的string/any)。以下是完整解决方案:
完整代码示例
interface A { type: 'a', option: { key: string value: any } } interface B { type: 'b' | 'c', option: { key: string secondKey: string value: any secondValue: any } } // 用const断言让TypeScript推断出字面量类型,保留具体的键名和值 const foo = [ { type: 'a', option: { key: 'keyOfA', value: 'valueOfA' } }, { type: 'b', option: { key: 'keyOfB', value: 'valueOfB', secondKey: 'secondKeyOfB', secondValue: 'secondValueOfB' } } ] as const; // 类型工具:将单个A/B元素转换为对应的键值对类型 type ElementToObj<X extends A | B> = X extends A ? { [K in X['option']['key']]: X['option']['value'] } : { [K in X['option']['key'] | X['option']['secondKey']]: K extends X['option']['key'] ? X['option']['value'] : X['option']['secondValue'] }; // 类型工具:递归合并数组中所有元素的键值对类型 type MergeArrayElements<T extends readonly (A | B)[]> = T extends readonly [infer First, ...infer Rest] ? ElementToObj<First> & MergeArrayElements<Rest> : {}; // 类型工具:将交叉类型转换为更友好的普通对象类型 type Flatten<T> = { [K in keyof T]: T[K] }; function fooFunc<T extends readonly (A | B)[]>(foo: T): Flatten<MergeArrayElements<T>> { return foo.reduce((prev, cur) => { if (cur.type === 'a') { return { ...prev, [cur.option.key]: cur.option.value } as Flatten<MergeArrayElements<T>>; } else { return { ...prev, [cur.option.key]: cur.option.value, [cur.option.secondKey]: cur.option.secondValue } as Flatten<MergeArrayElements<T>>; } }, {} as Flatten<MergeArrayElements<T>>); } // 测试:a的类型会被推断为 { keyOfA: "valueOfA"; keyOfB: "valueOfB"; secondKeyOfB: "secondValueOfB" } const a = fooFunc(foo);
关键步骤解释
保留字面量类型:给
foo添加as const断言,让TypeScript不再把key/value推断为宽泛的string/any,而是保留具体的字面量值(比如'keyOfA'、'valueOfA')。类型工具
ElementToObj:针对单个A或B类型,将其转换为对应的键值对对象类型:- 对于
A类型:提取option.key作为键,option.value作为值类型 - 对于
B类型:同时提取option.key和option.secondKey作为键,分别对应各自的value类型
- 对于
类型工具
MergeArrayElements:递归遍历数组的每个元素,把每个元素对应的ElementToObj类型交叉合并,实现累加的效果。类型工具
Flatten:把交叉类型(比如{keyOfA: string} & {keyOfB: string})转换为普通对象类型,让类型显示更直观友好。函数实现的类型断言:在
reduce的返回值和初始值处添加类型断言,告诉TypeScript当前的累加结果符合目标返回类型。
注意事项
如果你的数组元素可能存在重复键名,交叉类型会自动处理(重复键的类型会取交集)。如果需要覆盖重复键的类型,可以调整合并逻辑为替换式(需要更复杂的类型编程)。
内容的提问来源于stack exchange,提问作者xiaolee
相关产品推荐
相关产品推荐

