使用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
相关产品推荐
相关产品推荐

