React父子组件状态传递类型不兼容:自定义接口报错any正常
问题场景
在React项目中实现父组件状态传递给子组件、子组件管理状态的逻辑时,使用any类型代码能正常运行,但切换为自定义接口IChildForm后出现TypeScript类型错误:
类型为'IChildDetails[] | undefined'的参数无法赋值给类型为'MouseEvent<HTMLElement, MouseEvent>'的参数。类型'undefined'无法赋值给类型'MouseEvent<HTMLElement, MouseEvent>',错误代码ts(2345)
错误原因
子组件的IChildForm接口错误地将wrapper字段定义为React.MouseEventHandler<HTMLElement>类型——这是鼠标事件处理器类型,要求接收MouseEvent对象作为参数;但实际父组件传递的wrapper是用来接收状态数据(IChildDetails[] | undefined类型)的回调函数,两者类型完全不匹配,导致调用wrapper(childState)时触发类型校验错误。
解决方案
1. 修正子组件的接口定义
修改IChildForm接口中wrapper的类型,使其匹配实际接收的数据类型:
// Details_Form.tsx export interface IChildDetails { id?: string text: string } // 修正wrapper的类型定义,改为接收状态数据的回调函数 export interface IChildForm { details?: IChildDetails[] wrapper: (data: IChildDetails[] | undefined) => void } const compOne = ({ wrapper, details }: IChildForm) => { const [childState, setChildState] = useState(details); useEffect(() => { wrapper(childState); // 现在类型匹配,不会报错 }, [wrapper, childState]); // 其余组件逻辑... }
2. 修正父组件的回调函数类型
移除父组件中wrapper的any类型,替换为匹配的类型(可复用子组件导出的类型,或自行定义一致的类型):
// Parent.tsx export interface IDetails { id?: string text: string } export interface IMasterForm { details?: IDetails[] } const InitialState: IMasterForm = { details: [ {id: "1234567879", text:"hello world"} ] } const Page = () => { const [details, setDetails] = useState(InitialState.details) // 替换any为具体类型,与子组件的wrapper类型匹配 const wrapper = useCallback( (val: IDetails[] | undefined) => { setDetails(val); }, [setDetails] ); return( <Details_Form wrapper={wrapper} details={details}/> ) }
3. (可选)统一父子组件的详情类型
由于子组件是独立项目,后续要集成到父项目,建议将IDetails和IChildDetails统一为同一类型——可以把类型定义抽成独立的共享包,或者在子组件中复用父组件的类型(如果允许跨项目引用),避免因结构差异导致的隐性类型问题。
内容的提问来源于stack exchange,提问作者Bkirzor

