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

TypeScript协变逆变问题:Redux createStore传入Reducer类型报错

解决Redux Reducer类型不兼容(无需关闭strictFunctionTypes)

我完全懂你遇到的这个问题——开启strictFunctionTypes后,Redux的类型检查变得异常严格,本来逻辑上合理的reducer传入createStore就报错,核心就是函数参数的逆变特性在搞鬼:当createStore默认推断出宽泛的Action类型时,它期望reducer能处理所有这类Action,但你的reducer只针对特定的MyAction,严格模式下这种“窄类型转宽类型”的函数赋值是不被允许的(因为参数是逆变的,合法方向应该是宽类型转窄类型)。

不用关闭strictFunctionTypes,有几个优雅的解决方案:

1. 显式指定createStore的泛型参数

直接告诉TypeScript你的Store对应的State和Action类型,让它不要自动推断出宽泛的Action类型:

import { createStore } from 'redux';

// 定义你的状态和Action类型
type AppState = {};
type MyAction = { type: 'MY_ACTION' };

// 你的reducer
const myReducer = (state: AppState, action: MyAction) => {
  switch (action.type) {
    case 'MY_ACTION':
      // 处理你的业务逻辑
      return state;
    default:
      // 必须返回原state,避免类型错误
      return state;
  }
};

// 显式指定泛型参数,约束Action为MyAction
const store = createStore<AppState, MyAction>(myReducer);

2. 使用Redux官方的Reducer类型约束你的reducer

Redux提供了Reducer<S, A>类型,可以提前约束你的reducer的输入输出类型,避免后续类型推断混乱:

import { createStore, Reducer } from 'redux';

type AppState = {};
type MyAction = { type: 'MY_ACTION' };

// 用Reducer<S, A>明确约束reducer的类型
const myReducer: Reducer<AppState, MyAction> = (state, action) => {
  switch (action.type) {
    case 'MY_ACTION':
      return state;
    default:
      return state;
  }
};

// 此时createStore会自动识别正确的类型,无需额外指定
const store = createStore(myReducer);

3. (进阶)多Action类型场景

如果你的应用有多个Action类型,把它们合并成联合类型,再传递给泛型参数即可,同样能通过严格类型检查:

import { createStore, Reducer } from 'redux';

type AppState = {};
type MyAction = { type: 'MY_ACTION' };
type AnotherAction = { type: 'ANOTHER_ACTION'; payload: string };

// 联合Action类型
type AppActions = MyAction | AnotherAction;

const myReducer: Reducer<AppState, AppActions> = (state, action) => {
  switch (action.type) {
    case 'MY_ACTION':
      return state;
    case 'ANOTHER_ACTION':
      // 这里能正确推断action.payload的类型
      console.log(action.payload);
      return state;
    default:
      return state;
  }
};

const store = createStore(myReducer);

关键原理

开启strictFunctionTypes后,TypeScript会严格遵循函数参数的逆变规则:函数参数类型只能从宽类型收缩到窄类型,不能反过来。通过显式指定泛型或用Reducer类型约束,我们相当于告诉TypeScript:“这个Store只处理MyAction(或联合类型)”,这样createStore就不会期望reducer处理更宽泛的Action类型,自然就消除了类型不兼容的错误。

内容的提问来源于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:01:04