You need to enable JavaScript to run this app. TypeScript+Redux Toolkit:createSlice生成action调用出现冲突TS2554参数错误
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript+Redux Toolkit:createSlice生成action调用出现冲突TS2554参数错误

Redux Toolkit + TypeScript 冲突 TS2554 报错说明

问题场景

在 TypeScript 与 Redux Toolkit 技术栈下,调用 createSlice 创建的 action 时,会触发两类互相冲突的 TS2554 报错:「期望0个参数但实际传入1个」、「期望1个参数但实际传入0个」。

复现代码

export interface UffStatusState {
  fetchingPickStatus: APIState;
  activeMerchant: string | null;
  displayPicker: boolean | false;
}

const uffStatusSlice = createSlice({
  name: "uffStatus",
  initialState: {
    fetchingPickStatus: APIState.idle,
    activeMerchant: null,
    displayPicker: false,
  } as UffStatusState,
  reducers: {
    setfetchingPickStatus: (state, fetchingAction: PayloadAction<APIState>) => {
      state.fetchingPickStatus = fetchingAction.payload;
    },
    setActiveMerchant: (state, activeMerchantAction: PayloadAction<string>) => {
      state.activeMerchant = activeMerchantAction.payload;
    },
    setDisplayPicker: (state, display: PayloadAction<boolean>) => {
      state.displayPicker = display.payload
    },
  }
});

export const { setfetchingPickStatus, setActiveMerchant, setDisplayPicker } = uffStatusSlice.actions;
export default uffStatusSlice.reducer;

具体报错表现

  • 无参数调用 setDisplayPicker 时,会同时弹出两条互相冲突的报错:

    ERROR in src/components/HeaderBar.tsx:14:56 TS2554: Expected 0 arguments, but got 1.
    12 |
    13 | export default function HeaderBar() {

    14 | const handleSelectMerchants = () => useStoreDispatch(setDisplayPicker());
    | ^^^^^^^^^^^^^^^^^^
    15 | return (
    16 | <>
    17 | <KatRow className={'header'}>

    ERROR in src/components/HeaderBar.tsx:14:56 TS2554: Expected 1 arguments, but got 0.
    12 |
    13 | export default function HeaderBar() {

    14 | const handleSelectMerchants = () => useStoreDispatch(setDisplayPicker());
    | ^^^^^^^^^^^^^^^^^^
    15 | return (
    16 | <>
    17 | <KatRow className={'header'}>

  • 携带参数(无论传入 true 还是 false)调用 setDisplayPicker 时,会统一抛出「期望0个参数但获取到1个」的报错:

    ERROR in src/components/HeaderBar.tsx:14:56 TS2554: Expected 0 arguments, but got 1.
    12 |
    13 | export default function HeaderBar() {

    14 | const handleSelectMerchants = () => useStoreDispatch(setDisplayPicker(true));
    | ^^^^^^^^^^^^^^^^^^^^^^
    15 | return (
    16 | <>
    17 | <KatRow className={'header'}>

    ERROR in src/components/MerchantSelection.tsx:64:42 TS2554: Expected 0 arguments, but got 1.

    }
    const onDismiss = () => useStoreDispatch(setDisplayPicker(false));
    ^^^^^^^^^^^^^^^^^^^^^^^

    65 |
    66 | export default function MerchantSelection() {
    67 | const { displayPicker } = useStoreSelector( (state) => state.uffStoreSetting );

问题根因

RTK 的 createSlice 对 reducer 的类型推导有固定约定:

  • 每个 reducer 函数的第一个参数固定为当前状态,不需要手动添加类型注解
  • 第二个参数直接代表 action 的 payload 类型,RTK 会自动基于该参数的类型,生成对应 action creator 的入参类型,自动包装出完整的 PayloadAction<T> 结构
  • 手动给第二个参数添加 PayloadAction<T> 类型注解,会破坏 RTK 的类型推导逻辑:一方面会识别到 reducer 存在两个必填形参,推导 action creator 需要传入1个参数;另一方面又因为入参类型不符合内部推导规则,反向将 action creator 识别为无参数要求,最终出现互相冲突的 TS2554 报错。

修正方案

  1. 移除每个 reducer 第二个参数上的 PayloadAction<T> 类型注解,直接将参数类型标注为 payload 本身的原生类型即可:
    reducers: {
      setfetchingPickStatus: (state, fetchingValue: APIState) => {
        state.fetchingPickStatus = fetchingValue;
      },
      setActiveMerchant: (state, activeMerchantValue: string) => {
        state.activeMerchant = activeMerchantValue;
      },
      setDisplayPicker: (state, displayValue: boolean) => {
        state.displayPicker = displayValue
      },
    }
    
  2. 原接口定义中 displayPicker: boolean | false; 的写法属于冗余类型定义(false 本身就是 boolean 类型的子集),可简化为 displayPicker: boolean;,没有额外的类型约束效果。

调整完成后,RTK 会自动完成全链路类型关联:生成的 setDisplayPicker action creator 会被推导为必须传入1个 boolean 类型参数,调用时的类型校验会完全正常,不会再出现冲突报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.26 15:06:04