React TS中MUI TextField onChange报TS2345类型不匹配错误
React + TypeScript 中MUI TextField绑定onChange报类型错误修复
报错根因
MUI的TextField组件可根据配置渲染为原生<input>或<textarea>元素,因此它的onChange事件参数类型为React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,事件target是两种元素的联合类型。
你代码中自定义的updateHandler将事件参数类型写死为React.ChangeEvent<HTMLInputElement>,可接受的类型范围比实际传入的类型更窄,TypeScript校验不通过就会抛出该错误。
额外注意:原代码还存在闭包导致的状态更新滞后问题——setTodos回调中读取的editTodo是渲染闭包捕获的旧值,不是当前输入的最新内容,会出现输入内容和保存的待办内容差一个字符的情况。
修复方法
方法1:补全事件参数的联合类型
直接修改updateHandler的事件参数类型,和TextField实际抛出的事件类型对齐即可,两种原生元素都存在value属性,读取值不会有类型问题:
const updateHandler = ( e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>, id: number ) => { const inputValue = e.target.value; // 先更新编辑态的输入值 setEditTodo(inputValue); // 直接用最新的输入值更新待办列表,避免闭包旧值问题 setTodos(prevTodos => { return prevTodos.map(item => item.id === id ? { ...item, todo: inputValue } : item ); }); };
方法2:使用MUI内置的组件类型
直接引用MUI导出的TextField自带的onChange类型定义,不用手动写联合类型,后续MUI版本更新类型变动也不需要手动改:
// 导入TextField的属性类型 import type { TextFieldProps } from "@mui/material"; // 定义处理函数时直接复用内置类型 const updateHandler = ( e: Parameters<NonNullable<TextFieldProps["onChange"]>>[0], id: number ) => { const inputValue = e.target.value; setEditTodo(inputValue); setTodos(prevTodos => { return prevTodos.map(item => item.id === id ? { ...item, todo: inputValue } : item ); }); };
不推荐的方式:类型断言
可以在绑定事件时强制把事件类型断言为React.ChangeEvent<HTMLInputElement>绕过校验:
onChange={e => updateHandler(e as React.ChangeEvent<HTMLInputElement>, todo.id)}
这种写法相当于跳过TS类型检查,如果后续给TextField加multiline属性让它渲染为textarea,会出现隐藏的类型安全问题,非特殊场景不建议使用。
内容的提问来源于stack exchange,提问作者Amritpal Singh
相关产品推荐
相关产品推荐

