TypeScript如何为数组中每个函数成员独立推断参数类型
TypeScript 工具函数类型问题解决方案
这个需求完全可以通过TypeScript类型系统实现,原有写法报错的核心原因是泛型参数定义在函数根层级,整个数组的所有元素共享同一个泛型参数,TypeScript会统一合并所有元素的参数类型,无法为每个元组成员单独做类型匹配。
实现方案
使用映射元组类型对数组的每个成员单独做类型绑定,让TypeScript逐位校验每个[函数, 参数]元组的类型匹配关系,完整实现代码如下:
// 公共参数类型定义,按实际业务替换即可 interface CommonProps { token: string; } interface MyTypeFunction<T extends object = {}> { (params: T & CommonProps): any } function utilityHelper<T extends object[]>( param: [...{ [K in keyof T]: [MyTypeFunction<T[K]>, T[K]] }] ) { // 内部业务实现示例 // 1. 从Redux等上下文获取公共参数 // const commonProps: CommonProps = { token: store.getState().token } // 2. 合并参数后通过Redux-Saga all并行执行 // return all( // param.map(([fn, ownParams]) => call(fn, { ...ownParams, ...commonProps })) // ) }
效果验证
使用提供的示例代码调用时可以正常通过类型校验:
const functionA: MyTypeFunction<{ name: string }> = param => {}; const functionB: MyTypeFunction<{ id: number }> = param => {}; // 无类型报错 utilityHelper( [ [ functionA, { name: 'Name' } ], [ functionB, { id: 358 } ], ] );
如果传入的参数和对应函数不匹配,TypeScript也能精准抛出对应位置的错误,不会出现跨元素类型干扰的问题:
utilityHelper([ [functionA, { id: 123 }], // 报错:类型"{ id: number; }"缺少属性"name" [functionB, { id: 358 }], ])
实现原理
- 泛型
T extends object[]会收集传入数组中所有函数的自定义参数类型,组成一个元组类型,保留每个位置的精确类型 - 映射类型
{ [K in keyof T]: [MyTypeFunction<T[K]>, T[K]] }会遍历元组的每个索引位,给对应位置的函数和参数单独做类型绑定,每个位置的类型校验互不影响 - 外层包裹的
[... ]是可变元组标记,提示TypeScript对传入的数组做元组级别的精确推断,避免被推断为普通数组丢失位置类型信息
内容的提问来源于stack exchange,提问作者DanielYoshua
相关产品推荐
相关产品推荐

