TypeScript使用useReducer时出现ts(7053)索引类型错误如何解决?
TypeScript + useReducer 索引类型报错修复方案
核心原因
你的IAction接口中type定义为宽泛的string类型,TS无法保证运行时传入的type一定是IState的合法属性名,且特殊操作类型reset本身不属于IState的键,哪怕加了临时的类型断言也无法覆盖所有类型边界场景,因此持续抛出7053错误。
具体修改步骤
- 收窄Action的type类型范围
先定义合法的操作类型集合,将type的可选值限定为IState的属性名 + 特殊操作reset:
interface IState { email: string; password: string; passwordConfirmation: string; username: string; } // 新增:限定合法的action类型 type ActionType = keyof IState | 'reset' interface IAction { type: ActionType; value?: string; }
- 优化reducer逻辑,利用TS类型守卫自动收窄类型
排除reset分支后,剩余场景的type会被TS自动识别为keyof IState类型,不需要额外强制类型断言即可直接索引:
const reducer = (state: IState, action: IAction) => { if (action.type === "reset") { return initialState; } const result: IState = { ...state }; // 此处action.type已自动收窄为IState的合法键,不会触发类型错误 result[action.type] = action.value ?? ""; // 空值兜底避免value为undefined的类型警告 return result; };
- 可选:输入事件分发处添加类型断言(提升类型安全性)
因为input的name属性原生为string类型,分发时可以加一层断言确保类型匹配:
const onChange = (e: React.ChangeEvent<HTMLInputElement>) => { const { name, value } = e.target; dispatch({ type: name as keyof IState, value }); };
完整修复后代码
import React, { FC, Reducer, useReducer } from "react"; interface IState { email: string; password: string; passwordConfirmation: string; username: string; } type ActionType = keyof IState | 'reset' interface IAction { type: ActionType; value?: string; } const initialState: IState = { email: "", password: "", passwordConfirmation: "", username: "", }; const reducer = (state: IState, action: IAction) => { if (action.type === "reset") { return initialState; } const result: IState = { ...state }; result[action.type] = action.value ?? ""; return result; }; export const Signup: FC = props => { const [state, dispatch] = useReducer<Reducer<IState, IAction>, IState>(reducer, initialState, () => initialState); const { username, email, password, passwordConfirmation } = state; const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); /* fetch api */ /* clear state */ dispatch({ type: "reset" }); }; const onChange = (e: React.ChangeEvent<HTMLInputElement>) => { const { name, value } = e.target; dispatch({ type: name as keyof IState, value }); }; return ( <form onSubmit={handleSubmit}> <div> <label> Username: <input value={username} name="username" onChange={onChange} /> </label> </div> <div> <label> Email: <input value={email} name="email" onChange={onChange} /> </label> </div> <div> <label> Password: <input value={password} name="password" type="password" onChange={onChange} /> </label> </div> <div> <label> Confirm Password: <input value={passwordConfirmation} name="passwordConfirmation" type="password" onChange={onChange} /> </label> </div> <button>Submit</button> </form> ); };
内容的提问来源于stack exchange,提问作者Weilire
相关产品推荐
相关产品推荐

