TypeScript中createSelector按键选择器工厂的类型报错与正确实现
原选择器工厂存在的问题
原实现的运行时逻辑是正确的,但完全丢失了TypeScript的静态类型关联能力:
byKey函数的key参数被声明为联合类型keyof NodeState,TS无法区分当前传入的具体键对应的是哪个值类型- 因此
createSelector的返回值会被统一推断为所有状态值的联合类型Node[] | string - 当通过
useSelector获取选择器结果时,TS会把结果当成联合类型,调用仅存在于数组上的map方法时就会抛出类型错误。
适配TypeScript的正确实现方式
核心是通过泛型捕获传入的具体键,建立键名和对应值类型的静态关联,让TS能自动推导准确的返回类型:
- 先明确全局RootState的类型锚点,避免state参数隐式为any:
type RootState = { nodeList: NodeState; // 其他全局状态模块的类型定义 }; - 改造
byKey为泛型工厂函数:const nodeListState = (state: RootState) => state.nodeList; // 泛型K会捕获传入的具体键名类型 const byKey = <K extends keyof NodeState>(key: K) => createSelector( nodeListState, (nodeList: NodeState) => nodeList[key] // TS自动推导返回值类型为NodeState[K] ); - 按键生成的选择器会自动匹配对应的值类型:
export const getNodes = byKey('nodes'); // 返回值类型自动推导为 Node[] export const getText = byKey('text'); // 返回值类型自动推导为 string
使用效果
- 调用
useSelector(getNodes)时,TS会自动识别返回值为Node[],直接调用map方法不会再出现类型报错 - 调用
useSelector(getText)时,返回值会被识别为string,完全符合静态类型校验要求 - 后续新增NodeState的键时,工厂函数可以直接复用,不需要额外修改类型逻辑。
内容的提问来源于stack exchange,提问作者markkazanski
相关产品推荐
相关产品推荐

