TypeScript如何基于数组参数内对象的selector属性推导函数返回类型
解决方案
你需要为getData函数添加泛型支持,捕获传入的dataset数组的元组结构,并映射推导每个位置的返回类型。改造后的完整代码如下:
// 原有定义保持不变 type RootState = { a: boolean; b: string; }; const state: RootState = { a: true, b: "foo", }; type MakeDatasetConfig = <Selector extends { (a: RootState): unknown }>( selector: Selector ) => { selector: Selector; }; const makeDataset: MakeDatasetConfig = (selector) => ({ selector }); const selectA = (state: RootState) => state.a; const datasetA = makeDataset(selectA); const selectB = (state: RootState) => state.b; const datasetB = makeDataset(selectB); type Dataset = ReturnType<MakeDatasetConfig>; // 改造getData函数 const getData = <T extends Dataset[]>(datasets: readonly [...T]): { [K in keyof T]: ReturnType<T[K]['selector']> } => { const data = datasets.map(({ selector }) => selector(state)); // 手动断言返回类型,TS内置map方法无法推导元组结构 return data as { [K in keyof T]: ReturnType<T[K]['selector']> }; }; // 推导结果正确:a 的类型为 [boolean] const a = getData([datasetA]); // 推导结果正确:ab 的类型为 [boolean, string] const ab = getData([datasetA, datasetB]);
核心改造点说明
- 泛型参数
T extends Dataset[]用来捕获调用时传入的数组的精确元组结构(包括长度、每个位置的元素类型) - 用
readonly [...T]作为参数类型,引导TS将传入的数组字面量推导为元组而非普通数组 - 返回类型使用映射类型遍历元组的每个索引,提取对应位置dataset的selector返回值类型,最终得到和入参数组一一对应的元组返回类型
- 由于TS内置
Array.map的返回类型固定为普通数组,这里用类型断言标记返回值的实际类型,业务逻辑保证顺序和类型匹配的前提下,这个断言是安全的
该方案兼容TypeScript 4.3及以上版本,完全符合需求。
内容的提问来源于stack exchange,提问作者thatthatisis
相关产品推荐
相关产品推荐

