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

使用TypeScript配置ContextApi与useReducer时出现“No overload matches this call”错误

解决TypeScript中useReducer传入initialState时的ts(2769)类型错误

你碰到的这个No overload matches this call错误(代码ts(2769)),核心原因是reducer的类型定义不符合TypeScript对useReducer的类型要求,导致TypeScript无法正确推断state的类型,最终把它当成了never类型,自然就不接受你的IssuesInitialState类型的初始值了。

咱们一步步拆解问题根源和修复方案:

问题根源:Reducer的类型定义完全错误

你当前的IssueReducer接口把state和action打包成了一个对象参数,但useReducer要求的reducer函数签名是:

(state: StateType, action: ActionType) => StateType

而且你的reducer返回值类型写的是{},这完全不符合要求——reducer必须返回和初始state同类型的对象,TypeScript才能正确推断类型。另外,你的action类型太宽泛,只定义了type: string,没有明确所有可能的action类型,也会干扰类型推断。

修复步骤

1. 重新定义Reducer的Action与函数结构

先在IssuesReducer.ts里明确所有可能的action类型,修正reducer的参数和返回值类型:

// 导入你的基础类型
import { Issue, IssuesInitialState } from './Store';

// 枚举所有可能的action类型,每个action对应明确的payload结构
type IssueAction =
  | { type: 'FETCH_ISSUES'; payload: Issue[] }
  | { type: 'SET_ISSUE'; payload: Issue }
  | { type: 'SET_ISSUES_BY_PROJECT'; payload: Issue[] }
  | { type: 'SET_UPDATE_ISSUE'; payload: Issue };

// 修正reducer的类型:参数是state和action,返回值必须是IssuesInitialState
export const issuesReducer = (state: IssuesInitialState, action: IssueAction): IssuesInitialState => {
  switch (action.type) {
    case 'FETCH_ISSUES':
      return { ...state, issues: action.payload };
    case 'SET_ISSUE':
      return { ...state, issue: action.payload };
    case 'SET_ISSUES_BY_PROJECT':
      return { ...state, issuesByProject: action.payload };
    case 'SET_UPDATE_ISSUE':
      return { ...state, updateIssue: action.payload };
    // 必须添加默认case,返回原state,避免类型推断失败
    default:
      return state;
  }
};

2. 优化Context的类型定义

在Store.tsx里,不要用any来定义issuesDispatch和Provider的props,用具体类型替代,让类型检查更严谨:

import { createContext, useReducer, ReactNode } from 'react';
import { issuesReducer, IssueAction } from './IssuesReducer';

// 你的Issue和IssuesInitialState定义保持不变
type Issue = {
  closeDate: string | null;
  description: string;
  issueId: number;
  lastEditDate: string | null;
  priorityId: string;
  projectId: number;
  reportDate: string;
  statusId: string;
  title: string;
  userId: number;
};
interface IssuesInitialState {
  issues: Issue[];
  issue: Issue;
  issuesByProject: Issue[];
  updateIssue: Issue;
}
const issuesInitialState: IssuesInitialState = {
  issues: [],
  issue: {
    closeDate: "",
    description: "",
    issueId: 0,
    lastEditDate: "",
    priorityId: "",
    projectId: 0,
    reportDate: "",
    statusId: "",
    title: "",
    userId: 0,
  },
  issuesByProject: [],
  updateIssue: {
    closeDate: "",
    description: "",
    issueId: 0,
    lastEditDate: "",
    priorityId: "",
    projectId: 0,
    reportDate: "",
    statusId: "",
    title: "",
    userId: 0,
  },
};

// 优化Context类型,用React.Dispatch指定dispatch的action类型
export const IssuesContext = createContext<{
  issuesState: IssuesInitialState;
  issuesDispatch: React.Dispatch<IssueAction>;
}>({
  issuesState: issuesInitialState,
  issuesDispatch: () => {}
});

// Provider的props用ReactNode替代any,明确子元素类型
export function StoreProvider({ children }: { children: ReactNode }): JSX.Element {
  // 现在useReducer能正确推断类型,不会再报错
  const [issuesState, issuesDispatch] = useReducer(
    issuesReducer,
    issuesInitialState
  );

  // 如果你还有comments相关逻辑,记得同步修正它的reducer类型
  // const [commentsState, commentsDispatch] = useReducer(commentsReducer, commentsInitialState);

  return (
    <IssuesContext.Provider value={{ issuesState, issuesDispatch }}>
      {children}
    </IssuesContext.Provider>
  );
}

3. 关键注意点

  • Reducer必须返回同类型state:每个switch case都要返回state的副本,默认case一定要返回原state,否则TypeScript会认为reducer可能返回undefined,导致类型推断失败。
  • 明确Action类型:不要用宽泛的string作为action的type,用字面量类型枚举所有可能的action,TypeScript会帮你检查每个case的payload是否匹配。
  • 杜绝any类型:Context的dispatch和Provider的props都要用具体类型,不要依赖any,否则会失去TypeScript的类型检查优势。

这样修改后,你原来的ts(2769)错误就会消失,整个状态管理的类型也会更加严谨。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 16:07:37