You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从Reducer函数对象推断含键与返回值类型的RootState?

问题描述

我有一个映射Reducer名称与对应Reducer函数的对象:

const reducers = {
  clients: ClientsReducer,
  mails:   MailsReducer,
  users:   UsersReducer,
  // ...
}

该reducers对象的类型定义如下:

interface Reducers {
  clients: (state: ClientsState, action: any) => ClientsState,
  mails:   (state: MailsState, action: any) => MailsState,
  users:   (state: UsersState, action: any) => UsersState,
  // ...
}

在应用中使用useSelector选择状态时,需要定义特定的RootState类型:

interface RootState {
  clients: ClientsState;
  mails:   MailsState;
  users:   UsersState;
  // ...
}

// 使用示例
const clients = useSelector((state: RootState) => state.clients);

Redux官方建议通过combineReducers的结果推断该类型:

type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;

const rootState = combineReducers({
  ...reducers
});

type RootState = ReturnType<typeof rootState>;

但我的Store是通过不同模块动态创建的,无法获取combineReducers的结果,因此该方法不适用。

我尝试实现的类型如下:

type StateType<T extends Record<S, (...args: any) => any>, S extends string> = T extends Record<S, (...args: any) => infer R> ? Record<S, R> : any;

type RootState = StateType<typeof reducers, keyof typeof reducers>;

/*
 * 得到的错误结果:
 * RootState = {
 *    clients: ClientsState | MailsState | UsersState;
 *    mails:   ClientsState | MailsState | UsersState;
 *    users:   ClientsState | MailsState | UsersState;
 * }
 */

这个结果不正确,每个键对应的类型是所有状态的联合类型。我知道是泛型S导致的问题,但不知道如何修复。

请问是否有方法从reducers对象推断出正确的RootState类型,使其包含对应的键(Reducer名称)和函数返回值(Reducer状态)?


解决方案

可以通过TypeScript的映射类型实现精准的类型推断,逐个处理reducers对象的每个键,提取对应Reducer函数的返回值类型:

方式1:基于已定义的Reducers接口

// 工具类型:提取Reducer函数的返回值类型
type ReducerState<T> = T extends (...args: any[]) => infer R ? R : never;

// 遍历Reducers的每个键,映射为对应Reducer的返回值类型
type RootState = {
  [K in keyof Reducers]: ReducerState<Reducers[K]>;
};

方式2:基于typeof reducers直接推断

如果不想依赖预先定义的Reducers接口,也可以直接从reducers对象的类型推断:

type ReducerState<T> = T extends (...args: any[]) => infer R ? R : never;

type RootState = {
  [K in keyof typeof reducers]: ReducerState<(typeof reducers)[K]>;
};

原理说明

之前的实现失败是因为泛型S接收的是keyof typeof reducers这个联合类型,Record<S, ...>会将所有键统一映射为所有Reducer返回值的联合类型。而映射类型[K in keyof ...]会逐个遍历每个键,对每个键K单独提取对应Reducer的返回值类型,从而保证每个键与状态类型的一一对应关系。


内容的提问来源于stack exchange,提问作者Gartenzwerg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 10:42:45