在TypeScript中的React事件类型

30

当我在事件处理程序中使用MouseEvent类型时,我无法构建我的React/TypeScript应用程序:

private ButtonClickHandler(event: MouseEvent): void
{
    ...
}

我得到:

error TS2322: Type '{ onClick: (event: MouseEvent) => void; children: string; }' is not assignable to type 'DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>'.
  Type '{ onClick: (event: MouseEvent) => void; children: string; }' is not assignable to type 'ButtonHTMLAttributes<HTMLButtonElement>'.
    Types of property 'onClick' are incompatible.
      Type '(event: MouseEvent) => void' is not assignable to type 'EventHandler<MouseEvent<HTMLButtonElement>>'.
        Types of parameters 'event' and 'event' are incompatible.
          Type 'MouseEvent<HTMLButtonElement>' is not assignable to type 'MouseEvent'.
            Property 'fromElement' is missing in type 'MouseEvent<HTMLButtonElement>'.`

我也尝试过MouseEvent<HTMLButtonElement>,但是我得到了error TS2315: Type 'MouseEvent' is not generic.

为什么?

来自我的package.json的摘录:

 "devDependencies": {
    "@types/react": "^16.0.7",
    "@types/react-dom": "^15.5.5",
    "ts-loader": "^2.3.7",
    "typescript": "^2.5.3",
    "webpack": "^3.6.0"
  },
  "dependencies": {
    "react": "^16.0.0",
    "react-dom": "^16.0.0"
  }

编辑 #1:

render()中的绑定:

<button onClick={ this.ButtonClickHandler }>Toggle</button>

constructor 中:

this.ButtonClickHandler = this.ButtonClickHandler.bind(this);

请问您能否展示一下绑定该处理程序到元素的代码?我认为这个问题可能有根本原因。 - Nikolay Osaulenko
你的意思是在render和constructor中绑定吗?这部分已经添加在编辑 #1 中了。 - tBlabs
你尝试了吗 (event: React.MouseEvent<HTMLButtonElement>) - JulCh
是的,效果相同。似乎其他人没有这样的问题: https://www.bennadel.com/blog/3293-hello-world-with-webpack-and-typescript-2-3-4-in-react-15-6-1.htm - tBlabs
private ButtonClickHandler(event: React.MouseEvent<HtmlButtonElement>): void 应该可以工作。 - paibamboo
它给出了以下错误信息:error TS2304: 无法找到名称 'HtmlButtonElement'error TS2352: 类型 'MouseEvent<any>' 不能转换为类型 'MouseEvent'。属性 'fromElement' 在类型 'MouseEvent<any>' 中缺失 - tBlabs
3个回答

49
我认为这里发生的情况是有两种不同的类型可用:jsx/lib/js/js/web.jsx中的MouseEvent(它没有类型参数),以及@types/react/index.d.ts中的React.MouseEvent<T>(它有一个类型参数T,表示它来自哪个元素的类型)。Typescript使用结构化类型,所以即使它们是不同的类型,它们也可以兼容。但是为了与onClick处理程序兼容,您需要使用React的版本,并为THTMLElement将起作用,或者如果您知道要附加此处理程序的元素,则可以更具体)使用适当的类型。
因此,event: MouseEvent失败,因为onClick需要特定版本的事件类型。 event: MouseEvent<HTMLElement>失败,因为它引用了错误的MouseEvent类型,即没有类型参数的那个类型。 React.MouseEvent<HTMLElement>是有效的,因为它给出了正确的类型,给出了所需的参数,生成的类型与onClick处理程序兼容。

2
谢谢,这也帮助了我。似乎很遗憾的是,使用React时,这些基本问题在TypeScript中无法直接解决。添加一个onClick事件需要这么多的Google搜索才能让它正常工作。 - dcsan
你可以使用 React.MouseEvent<Element> 来使代码更加开放。 - desenV

36

我曾遇到相同的问题,但通过明确从 React 导入 MouseEvent 解决了它。

我遇到了这个错误。

import React from 'react';

但是使用这种方法可以解决这个问题。

import React, { MouseEvent } from 'react';

5
你不会相信:只需要将构造函数分配移到渲染函数中就足够了。
render()
{
return (
<button onClick={ this.Button_Click.bind(this) }>Toggle</button>
)}

然后 MouseEvent 变得可用:
private Button_Click(event: MouseEvent): void

为什么会发生这种情况?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接