React TS中onClick类型报错:事件对象与自定义参数冲突
问题
尝试在自定义Button组件的onClick处理函数中传入自定义变量,功能可正常运行,但TypeScript抛出类型错误。
类型定义
export type ButtonType = { name: string; buttonStyle: string; onClick?: (id: number) => void; };
可复用Button组件
return ( <button type="submit" className={buttonTypeStyle(buttonStyle)} onClick={onClick} > {name} </button> ); };
UrlList组件中的使用
const handleOnCLick = (id: number) => { return copiedUrlId !== id ? dispatch(setCopiedAction({ id })) : 0; }; return ( <section className={style.container}> <ul className={style.container__urlList}> {urls.length > 0 && urls.map((url: any) => { return ( <li key={urls.id} className={style.container__url}> <p>original url</p> <hr /> <div className={style.container__urlDivider}> <p>{url.shortenUrl}</p> <Button name={`${copiedUrlId === url.id ? "Copied!" : "Copy"}`} buttonStyle={ copiedUrlId === url.id ? "smallSquareCopied" : "smallSquare" } onClick={() => handleOnCLick(url.id)} /> </div> </li> ); })} </ul> </section> );
报错信息
TS2322: Type '((id: number) => void) | undefined' is not assignable to type 'MouseEventHandler<HTMLButtonElement> | undefined'. Type '(id: number) => void' is not assignable to type 'MouseEventHandler<HTMLButtonElement>'. Types of parameters 'id' and 'event' are incompatible. Type 'MouseEvent<HTMLButtonElement, MouseEvent>' is not assignable to type 'number'. 16 | type="submit" 17 | className={buttonTypeStyle(buttonStyle)} > 18 | onClick={onClick} | ^^^^^^^ 19 | > 20 | {name} 21 | </button>
推测是原生onClick默认传递event对象,TypeScript将其与自定义变量id混淆导致类型冲突,该如何解决?
解决方案
核心问题是:原生<button>的onClick期望接收MouseEventHandler<HTMLButtonElement>类型(即接收MouseEvent参数的函数),但你定义的ButtonType中onClick是接收number类型参数的函数,两者类型不匹配。以下是三种可行解决方法:
方法一:修正ButtonType的onClick类型(推荐)
你在UrlList中传入的onClick是() => handleOnCLick(url.id)——这是一个无参数函数,已经通过闭包绑定了url.id。因此直接修改ButtonType的onClick类型为无参数函数,即可完美匹配:
export type ButtonType = { name: string; buttonStyle: string; onClick?: () => void; };
Button组件代码无需修改,因为无参数函数可以兼容原生onClick(原生会传递event,但函数可选择不接收),TypeScript会自动通过类型检查。
方法二:在Button组件中包装传入的onClick
如果需要保留原ButtonType的类型定义,可在Button组件内将传入的onClick包装成符合原生事件要求的函数,忽略原生event参数:
return ( <button type="submit" className={buttonTypeStyle(buttonStyle)} onClick={() => { onClick?.(); }} > {name} </button> ); };
方法三:让onClick同时兼容event和自定义参数
若需要在Button组件中同时获取原生event和自定义id,可调整类型定义并修改组件逻辑:
- 更新类型定义:
export type ButtonType = { name: string; buttonStyle: string; onClick?: (event: React.MouseEvent<HTMLButtonElement>, id: number) => void; id?: number; };
- 修改Button组件:
return ( <button type="submit" className={buttonTypeStyle(buttonStyle)} onClick={(event) => { onClick?.(event, id); }} > {name} </button> ); };
- 在UrlList中使用:
<Button name={`${copiedUrlId === url.id ? "Copied!" : "Copy"}`} buttonStyle={copiedUrlId === url.id ? "smallSquareCopied" : "smallSquare"} id={url.id} onClick={(event, id) => handleOnCLick(id)} />
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

