TypeScript中使用Array.prototype.reduce()访问Redux状态的类型问题
解决TypeScript中用
Array.reduce访问Redux嵌套状态的类型报错问题 这个问题我之前也碰到过——TypeScript的类型系统没办法自动追踪reduce遍历字符串数组时每一步的accumulator类型变化,毕竟它只知道数组元素是string,但不知道这些字符串具体对应Redux state上的哪个属性,所以会把accumulator的类型逐步收窄到unknown,最后导致类型不匹配的报错。下面给你几个可行的解决方案,从简单到通用:
1. 针对固定路径的手动类型标注
如果你的路径是固定的(比如永远是["orders", "delay"]),可以直接给reduce的回调函数手动标注accumulator的类型,一步步明确每一步的结构:
const state = store.getState(); // 手动标注accumulator的类型,让TS知道每一步的结构 const path = ["orders", "delay"].reduce( (accumulator: { orders: { delay: string } }, currentValue) => accumulator[currentValue], state );
这种方式简单直接,但缺点是如果路径变化,你就得手动修改类型标注,不够灵活。
2. 通用的类型安全嵌套访问工具函数
如果需要频繁访问不同的嵌套路径,最好写一个通用的类型安全工具函数,让TypeScript自动推断路径对应的返回类型。先定义几个递归类型工具,再实现函数:
// 递归类型:获取对象的所有嵌套路径(支持字符串或数组形式) type ObjectPaths<T> = T extends object ? { [K in keyof T]: K | `${K}.${ObjectPaths<T[K]>}` }[keyof T] : never; // 递归类型:根据路径获取对应的值类型 type PathValueType<T, P extends ObjectPaths<T>> = P extends `${infer Key}.${infer Rest}` ? Key extends keyof T ? PathValueType<T[Key], Rest extends ObjectPaths<T[Key]> ? Rest : never> : never : P extends keyof T ? T[P] : never; // 类型安全的嵌套值获取函数 function getNestedValue<T, P extends ObjectPaths<T>>(obj: T, path: P): PathValueType<T, P>; function getNestedValue(obj: any, path: string | string[]): any { const pathSegments = Array.isArray(path) ? path : path.split('.'); return pathSegments.reduce((acc, key) => acc[key], obj); }
然后用这个函数访问你的Redux state,TypeScript会自动推断返回值的类型:
const state = store.getState(); // 字符串路径形式,TS自动推断返回值是string const delay = getNestedValue(state, "orders.delay"); // 数组路径形式,同样能正确推断类型 const delayFromArray = getNestedValue(state, ["orders", "delay"]);
这种方式既灵活又安全,适合在项目中复用。
3. 临时方案:类型断言(谨慎使用)
如果你只是临时解决问题,不想写复杂的类型工具,可以用类型断言,但要注意这会跳过TypeScript的类型检查,所以要确保路径是正确的:
const state = store.getState(); const path = ["orders", "delay"].reduce( (accumulator, currentValue) => accumulator[currentValue] as string, state as any // 或者更精确地标注为RootState["orders"] );
注意:尽量避免用any,最好用你定义的RootState类型来断言,比如:
type RootState = ReturnType<typeof store.getState>; const path = ["orders", "delay"].reduce( (acc, curr) => acc[curr] as RootState["orders"]["delay"], state as RootState );
额外提示
确保你的Redux state已经有明确的类型定义(比如通过ReturnType<typeof store.getState>生成RootState),这会让所有的类型标注更清晰准确。
内容的提问来源于stack exchange,提问作者Andrew
相关产品推荐
相关产品推荐

