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

TypeScript使用useReducer时出现ts(7053)索引类型错误如何解决?

TypeScript + useReducer 索引类型报错修复方案

核心原因

你的IAction接口中type定义为宽泛的string类型,TS无法保证运行时传入的type一定是IState的合法属性名,且特殊操作类型reset本身不属于IState的键,哪怕加了临时的类型断言也无法覆盖所有类型边界场景,因此持续抛出7053错误。

具体修改步骤

  1. 收窄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;
}
  1. 优化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;
};
  1. 可选:输入事件分发处添加类型断言(提升类型安全性)
    因为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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 23:06:04