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

为带可选dispatch的useReducer添加TypeScript类型求助

为支持可选dispatch的useReducer reducer添加TypeScript类型

这个模式允许两种dispatch调用方式:不传参时切换当前布尔状态,传入布尔值时直接设置状态。但添加基础类型后,传参调用toggle(true)/toggle(false)会触发TypeScript错误,提示“Expected 0 arguments, but got 1”。

原代码(无类型)

[on, toggle] = useReducer(
  (prevState, next) => next == null ? !prevState : next, 
  false
)

尝试的代码(存在类型错误)

const [on, toggle] = useReducer(
  (prevState: boolean, next?: boolean) => (next == null ? !prevState : next),
  false
)

const enable = () => toggle(true) // Error Expected 0 arguments, but got 1.ts(2554)
const disable = () => toggle(false) // Error Expected 0 arguments, but got 1.ts
const toggleSwitch = () => toggle() // ☑️ 正常

解决方案

问题出在TypeScript对useReducer的dispatch类型推导:当reducer的第二个参数标记为可选(next?: boolean)时,TypeScript默认认为dispatch不需要参数。我们需要显式指定action的类型为boolean | undefined,让TypeScript知道dispatch可以接受布尔值或不传参。

方法1:显式定义action参数类型

const [on, toggle] = useReducer(
  (prevState: boolean, next: boolean | undefined) => next == null ? !prevState : next,
  false
);

const enable = () => toggle(true); // ☑️ 正常
const disable = () => toggle(false); // ☑️ 正常
const toggleSwitch = () => toggle(); // ☑️ 正常

方法2:使用泛型约束useReducer

const [on, toggle] = useReducer<(state: boolean, action?: boolean) => boolean>(
  (prevState, next) => next == null ? !prevState : next,
  false
);

// 调用均正常
const enable = () => toggle(true);
const disable = () => toggle(false);
const toggleSwitch = () => toggle();

这两种方式都能让TypeScript正确识别dispatch的参数规则——既可以不传参切换状态,也可以传入布尔值直接设置状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 10:10:23