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

映射类型与函数参数难题:Redux Reducer处理函数的类型问题

解决Redux Reducer Map的类型约束问题

我懂你碰到的这个痛点——当前的代码虽然能输出符合预期的类型,但拦不住非预期的输入(比如把'hello'这种字符串当成某个state字段对应的reducer传进去)。这本质是TypeScript泛型推断顺序的问题,而柯里化确实是搞定这类问题的绝佳方案,咱们一步步来解决:

先明确问题根源

你原来的代码大概是这样的(补全了截断的部分):

type Reducer<State> = (s: State, p: any) => State;
const reducerMap = <State>(s: State) => <ScopedReducers extends { [k in keyof State]: Reducer<State[k]> }>(input: ScopedReducers) => {
  // 你的reducer合并逻辑
};

这里的问题在于:TypeScript会优先推断State类型,但它可能会为了满足ScopedReducers的约束,扭曲State的推断结果,或者干脆放松检查,导致不符合Reducer类型的输入混进来。

柯里化调整方案

我们把泛型参数拆分成两层柯里化,先锁定State类型,再约束传入的reducers,这样TypeScript的类型检查就会严格起来:

type Reducer<State> = (state: State, action: any) => State;

// 外层函数先指定State类型,内层函数接收符合约束的reducers
const createReducerMap = <State>() => {
  return <ScopedReducers extends Record<keyof State, Reducer<State[keyof State]>>>(
    reducers: ScopedReducers
  ) => {
    // 示例:实现一个合并scoped reducers的根reducer
    return (currentState: State, action: any): State => {
      const updatedState = { ...currentState };
      Object.entries(reducers).forEach(([key, reducer]) => {
        updatedState[key as keyof State] = reducer(updatedState[key as keyof State], action);
      });
      return updatedState;
    };
  };
};

使用示例(严格约束生效)

// 先定义你的应用State类型
type AppState = {
  count: number;
  username: string;
};

// 第一步:锁定State类型,此时后续的reducers会被严格校验
const buildAppReducers = createReducerMap<AppState>();

// ✅ 合法输入:每个字段都传入符合Reducer类型的函数
const validRootReducer = buildAppReducers({
  count: (state, action) => state + (action.payload ?? 1),
  username: (state, action) => action.payload || state
});

// ❌ 非法输入:TypeScript会直接报错,拦截非预期的输入
const invalidRootReducer = buildAppReducers({
  count: (state, action) => state + 1,
  username: 'hello' // 报错:类型'string'不能赋值给类型'Reducer<string>'
});

为什么柯里化能解决问题?

通过把State泛型放在外层函数,我们强制TypeScript先确定State的类型,之后内层函数的ScopedReducers泛型就会基于这个固定的State做严格约束,不会再为了匹配输入而调整State的推断。这样就能彻底阻止不符合要求的非预期输入,同时保证输出的根reducer类型完全符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 04:11:30