如何为对象fastMap添加泛型类型以实现正确类型推导?
解决方案
核心问题是fastMap初始类型为{},TypeScript无法跟踪动态添加的条目类型,我们可以通过明确类型定义、泛型约束来解决这个问题:
1. 定义基础类型
先抽离单个条目的类型,确保每个属性的类型都清晰:
import { atom } from 'jotai'; // 假设你使用Jotai的atom,按需调整 import { PayloadAction } from '@reduxjs/toolkit'; // 确保你的RootState和SliceState已提前定义 type RootState = { /* 你的RootState结构 */ }; type SliceState = { /* 你的SliceState结构 */ }; // 单个FastMap条目的类型 type FastMapEntry<S, T> = { value: T; selector: (state: RootState) => T; atom: ReturnType<typeof atom<T>>; // 明确atom存储T类型的值 dispatch: (state: S, action: PayloadAction<any>) => void; }; // FastMap的基础索引类型 type FastMap = Record<string, FastMapEntry<any, any>>;
2. 初始化fastMap并约束addToFastMap泛型
修改addToFastMap,把key也作为泛型参数,同时在赋值时断言条目类型,还可以返回一个带类型的getter避免直接访问的类型模糊:
export const fastMap = {} as FastMap; export type FastMapOptions<K extends string, S, T> = { key: K; value: T; selector: (state: RootState) => T; dispatch: (state: S, action: PayloadAction<any>) => void; }; export const addToFastMap = <K extends string, S, T>(options: FastMapOptions<K, S, T>) => { const { key, value, selector, dispatch } = options; // 创建明确类型的atom const entryAtom = atom<T>({ key, default: value }); // 将条目断言为对应类型后存入fastMap fastMap[key] = { value, selector, atom: entryAtom, dispatch } as FastMapEntry<S, T>; // 返回带类型的getter函数,直接获取条目时自动匹配类型 return () => fastMap[key] as FastMapEntry<S, T>; };
3. 使用示例
调用addToFastMap时,泛型会自动推断(也可手动指定),通过返回的getter获取条目时能自动获得正确类型:
// 调用时自动推断泛型,或手动指定<"margin", SliceState, number> const getMarginEntry = addToFastMap({ key: "margin", value: 20, selector: (state: RootState) => state.properties.margin, dispatch: marginUpdatedReducer }); // 获取条目,TypeScript自动识别value为number类型 const marginEntry = getMarginEntry(); console.log(marginEntry.value); // 类型为number marginEntry.dispatch(/* 参数自动匹配SliceState和PayloadAction类型 */);
4. 预先定义所有key的类型(可选)
如果所有key都是已知的,可以预先定义FastMap的完整类型,这样直接访问fastMap[key]也能获得类型提示:
// 预先定义所有key对应的条目类型 type FastMapFinal = { margin: FastMapEntry<SliceState, number>; padding: FastMapEntry<SliceState, number>; // 其他key... }; // 初始化时断言为完整类型 export const fastMap = {} as FastMapFinal; // 调用addToFastMap时,TypeScript会检查key是否符合定义 addToFastMap({ key: "margin", // 合法,匹配类型定义 value: 20, selector: (state: RootState) => state.properties.margin, dispatch: marginUpdatedReducer }); // 直接访问时自动识别类型 const marginValue = fastMap.margin.value; // 类型为number
内容的提问来源于stack exchange,提问作者Daniel Ivory
相关产品推荐
相关产品推荐

