使用类型脚本和 React. Konva 指定 onClick 事件类型

我试图摆脱我的 tslint 错误 Type declaration of 'any' loses type-safety.,但我正在努力找出什么是正确的类型将事件。

我正在通过琳达“ 构建和部署全堆栈反应应用程序”工作,同时试图将其转换为打字机。

以下是造成这一问题的具体原因:

onClick={(event: any) => {
makeMove(ownMark, event.target.index)
}}

我尝试将事件声明为几种不同的类型,比如 React.MouseEvent<HTMLElement>,以及 HTMLElement 上的一些其他子类型,但没有成功,因为 target.index 不是我能想到的任何类型的属性。我可以从检查员那里看到目前的目标是 Konva。文本和索引被设置为 0,但不能肯定这对我有帮助,因为我不能设置类型为 Konva.Text,这对我来说是有意义的,但这也不工作。

React Konva Event target Index

下面是我的完整的 React 功能组件:

export const Squares = ({units, coordinates, gameState, win, gameOver, yourTurn, ownMark, move}: SquaresProps) => {
let squares = coordinates.map( (position: number, index: number) => {
let makeMove = move
let mark = gameState[index] !== 'z' ? gameState[index] : false
let fill = 'black'


// when someone wins you want the square to turn green
if (win && win.includes(index)) {
fill = 'lightGreen'
}


if (gameOver || !yourTurn || mark) {
makeMove = () => console.log('nope!')
}


return (
<Text
key={index}
x={position[0]}
y={position[1]}
fontSize={units}
width={units}
text={mark}
fill={fill}
fontFamily={'Helvetica'}
aligh={'center'}
onClick={(event: any) => {
makeMove(ownMark, event.target.index)
}}
/>
)
})


return (
<Layer>
{squares}
</Layer>
)
}

以下是我的 package.json依赖项:

  "dependencies": {
"konva": "^1.6.3",
"material-ui": "^0.18.4",
"react": "^15.6.1",
"react-dom": "^15.6.1",
"react-konva": "^1.1.3",
"react-router": "~3.0.0",
"react-tap-event-plugin": "^2.0.1",
"styled-components": "^2.1.0"
},

好好想想的索引是由 Konva 层类添加,但我是相当新的整个反应生态系统,所以仍然试图包裹我的大脑周围的一切。

UPDATE:

I was able use declaration merging suggestion by Tyler Sebastion to define the index on the target which silenced tslint. I'm not sure this is the best approach though as it feels a bit fragile to me.

下面是附加的接口代码和更新的 onclick 事件:

interface KonvaTextEventTarget extends EventTarget {
index: number
}


interface KonvaMouseEvent extends React.MouseEvent<HTMLElement> {
target: KonvaTextEventTarget
}


...


return (
<Text
key={index}
x={position[0]}
y={position[1]}
fontSize={units}
width={units}
text={mark}
fill={fill}
fontFamily={'Helvetica'}
aligh={'center'}
onClick={(event: KonvaMouseEvent) => {
makeMove(ownMark, event.target.index)
}}
/>
)
295105 次浏览

You're probably out of luck without some hack-y workarounds

你可以试试

onClick={(event: React.MouseEvent<HTMLElement>) => {
makeMove(ownMark, (event.target as any).index)
}}

我不确定你的衬垫有多严格——这样可能会让它闭上一点点嘴

我用它玩了一会儿,还是没有弄明白,但是您也可以考虑编写自己的增强定义: https://www.typescriptlang.org/docs/handbook/declaration-merging.html

编辑: 请使用 本回覆中的实现,它是 解决这个问题的正确方法(当你在这里的时候,也给他投上一票)。

正如我在上面的更新中提到的,一个潜在的解决方案是使用@Tyler-sebastion 建议的声明合并。我能够定义另外两个接口,并以这种方式在 EventTarget上添加 index 属性。

interface KonvaTextEventTarget extends EventTarget {
index: number
}


interface KonvaMouseEvent extends React.MouseEvent<HTMLElement> {
target: KonvaTextEventTarget
}

然后可以在 onclick MouseEventHandler 函数中将事件声明为 KonvaMouseEvent

onClick={(event: KonvaMouseEvent) => {
makeMove(ownMark, event.target.index)
}}

如果这是最好的方法,我仍然不是100% ,因为它感觉有点笨拙和过于冗长,只是为了通过 tslint 错误。

反应。鼠标事件为我工作:

private onClick = (e: React.MouseEvent<HTMLInputElement>) => {
let button = e.target as HTMLInputElement;
}

您应该使用 event. currentTarget。React 反映了 currentTarget (事件附加到的元素)和 target (事件当前发生的元素)之间的区别。由于这是一个鼠标事件,因此两者在类型上可能有所不同,即使对于单击没有意义。

Https://github.com/facebook/react/issues/5733 Https://developer.mozilla.org/en-us/docs/web/api/event/currenttarget

摘自 ReactKonvaCore.d.ts 文件:

onClick?(evt: Konva.KonvaEventObject<MouseEvent>): void;

所以,我会说你的事件类型是 Konva.KonvaEventObject<MouseEvent>

你可以这样做

   onClick: React.MouseEventHandler<HtmlInputElement> = (e) => {
const button = e.target as HTML
}

您可以使用 IDE/编辑器中的 IntelliSense (或等效的)来确定类型。将事件处理程序暂时与 HTML 元素保持一致,然后将鼠标悬停在该事件上。艾格。

<button onClick={(event => console.log(event))}>Click me</button>

在 VSCode 中悬停在 event上显示:

(parameter) event: React.MouseEvent<HTMLButtonElement, MouseEvent>

I think the correct type is

event:React.MouseEvent<HTMLButtonElement, MouseEvent>