问题
I'm trying to get rid of my tslint error Type declaration of 'any' loses type-safety.
but I'm struggling to figure out what the correct type would be for the Event.
I'm working through the Lynda "Building and Deploying a Full-Stack React Application" while trying to convert it to Typescript.
Here are the specific lines that are causing the issue:
onClick={(event: any) => {
makeMove(ownMark, event.target.index)
}}
I have tried to declare the event as a few different types, like React.MouseEvent<HTMLElement>
, plus a few other subtypes on HTMLElement, with no success as the target.index is not a property on any type I can come up with. I can see from the inspector that the currentTarget is Konva.Text and the index is set to 0
but not sure that helps me as I can't set the type to Konva.Text
, which would make sense to me, but that doesn't work either.
Here is my full React functional component:
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>
)
}
Here are my package.json
dependencies:
"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"
},
I think the index is being added by the Konva Layer class but I'm pretty new to the whole react ecosystem so still trying to wrap my brain around it all.
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.
Here is the additional interface code and updated onclick event:
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)
}}
/>
)
回答1:
You're probably out of luck without some hack-y workarounds
You could try
onClick={(event: React.MouseEvent<HTMLElement>) => {
makeMove(ownMark, (event.target as any).index)
}}
I'm not sure how strict your linter is - that might shut it up just a little bit
I played around with it for a bit, and couldn't figure it out, but you can also look into writing your own augmented definitions: https://www.typescriptlang.org/docs/handbook/declaration-merging.html
edit: please use the implementation in this reply it is the proper way to solve this issue (and also upvote him, while you're at it).
回答2:
As posted in my update above, a potential solution would be to use Declaration Merging as suggested by @Tyler-sebastion. I was able to define two additional interfaces and add the index property on the EventTarget
in this way.
interface KonvaTextEventTarget extends EventTarget {
index: number
}
interface KonvaMouseEvent extends React.MouseEvent<HTMLElement> {
target: KonvaTextEventTarget
}
I then can declare the event as KonvaMouseEvent
in my onclick MouseEventHandler function.
onClick={(event: KonvaMouseEvent) => {
makeMove(ownMark, event.target.index)
}}
I'm still not 100% if this is the best approach as it feels a bit Kludgy and overly verbose just to get past the tslint error.
回答3:
React.MouseEvent works for me:
private onClick = (e: React.MouseEvent<HTMLInputElement>) => {
let button = e.target as HTMLInputElement;
}
回答4:
You should be using event.currentTarget. React is mirroring the difference between currentTarget (element the event is attached to) and target (the element the event is currently happening on). Since this is a mouse event, type-wise the two could be different, even if it doesn't make sense for a click.
https://github.com/facebook/react/issues/5733 https://developer.mozilla.org/en-US/docs/Web/API/Event/currentTarget
来源:https://stackoverflow.com/questions/45089866/specifying-onclick-event-type-with-typescript-and-react-konva