TypeScript:为对象所有属性应用泛型函数并推导返回值
TypeScript批量转换选择器对象的类型标注方案
我在TypeScript中实现了单个选择器的转换函数createModifiedSelector,但当选择器数量较多时,希望批量转换整个选择器对象,目前的createModifiedSelectorsObj存在类型标注问题:需要替换Record<keyof R, any>中的any,同时解决循环中createModifiedSelector调用的TS2345类型错误。
原代码如下:
type State = { alpha: string, beta: number } const selectors = { alpha: (s: State) => s.alpha, beta: (s: State) => s.beta } function createModifiedSelector<T, S, U>( modifyState: (differentState: T) => S, selector: (state: S) => U, ) { return (differentState: T) => selector(modifyState(differentState)); } const add2State = (state: any) => { return {...state, alpha: "abc", beta: 123} } // 单个选择器转换可正常运行 const modifiedAlpha = createModifiedSelector(add2State, selectors.alpha) console.log(modifiedAlpha({})); // 批量转换选择器对象的函数存在类型问题 function createModifiedSelectorsObj<T, S, R extends typeof selectors>(modifyState: (differentState: T) => S, selectors: R) { const result: Record<keyof R, any> = selectors; // 这里应该用什么类型替代any? let selectorKey: keyof R; for (selectorKey in selectors) { result[selectorKey] = createModifiedSelector(modifyState, selectors[selectorKey]) // 如何解决TS2345错误? } return result; }
修正后的完整实现
通过映射类型定义返回值结构,并通过类型断言解决循环中的类型不兼容问题,以下是正确的代码:
type State = { alpha: string, beta: number } const selectors = { alpha: (s: State) => s.alpha, beta: (s: State) => s.beta } function createModifiedSelector<T, S, U>( modifyState: (differentState: T) => S, selector: (state: S) => U, ) { return (differentState: T) => selector(modifyState(differentState)); } const add2State = <T>(state: T) => { return {...state, alpha: "abc", beta: 123} as const; } // 映射类型:将原选择器转换为接收T类型参数的新函数 type ModifiedSelectors<T, R> = { [K in keyof R]: R[K] extends (state: infer S) => infer U ? (differentState: T) => U : never; }; function createModifiedSelectorsObj<T, S, R extends Record<string, (state: S) => any>>( modifyState: (differentState: T) => S, selectors: R ): ModifiedSelectors<T, R> { const result = {} as ModifiedSelectors<T, R>; for (const selectorKey in selectors) { if (selectors.hasOwnProperty(selectorKey)) { result[selectorKey] = createModifiedSelector(modifyState, selectors[selectorKey]) as ModifiedSelectors<T, R>[typeof selectorKey]; } } return result; } // 使用示例 const modifiedSelectors = createModifiedSelectorsObj(add2State, selectors); // 类型正确:modifiedSelectors.alpha() 返回 string,modifiedSelectors.beta() 返回 number console.log(modifiedSelectors.alpha({})); // "abc" console.log(modifiedSelectors.beta({})); // 123
核心要点
- 映射类型
ModifiedSelectors:遍历原选择器对象的每个键,通过条件类型推断原选择器的输入和输出类型,将其转换为接收T类型参数的新函数 - 泛型约束:将
R约束为Record<string, (state: S) => any>,确保每个属性都是符合要求的选择器函数 - 类型断言:初始化
result时断言为目标类型,赋值时再次断言对应键的类型,绕过TypeScript对循环赋值的类型检查限制
内容的提问来源于stack exchange,提问作者Sentenza
相关产品推荐
相关产品推荐

