Reputation: 407
I'm having problems with the strictness of Typescript when using event handlers with React. Specifically, I am unable to use object destructuring with my handleClick()
function that goes on the onClick={handleClick}
attribute.
This is the unclean version, and it is the only one typescript acceps without complaining:
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
const target: Element = event.target as Element
// ...other code goes here
}
This is the clean version, and typescript throws errors:
const handleClick = ({ target }: { target: Element }) => {
// ...other code goes here
}
The second block of code (the unclean version) causes Typescript to throw an error. When I hover over the onClick={handleClick} attribute, this frutratingly cryptic error is displayed:
Type '({ target }: { target: Element; }) => void' is not assignable to type 'MouseEventHandler'. Types of parameters '__0' and 'event' are incompatible. Type 'MouseEvent<HTMLButtonElement, MouseEvent>' is not assignable to type '{ target: Element; }'. Types of property 'target' are incompatible. Type 'EventTarget' is missing the following properties from type 'Element': attributes, classList, className, clientHeight, and 120 more.ts(2322) index.d.ts(1457, 9): The expected type comes from property 'onClick' which is declared here on type 'DetailedHTMLProps<ButtonHTMLAttributes, HTMLButtonElement>'
Does anybody have a solution to this? I am stumped.
Thank you in advance.
Upvotes: 4
Views: 12302
Reputation: 15106
You can just use the same type React.MouseEvent<HTMLButtonElement>
for the destructured parameter. This will infer the correct type for target
. You'll probably want to use currentTarget
though, which is the element the handler was attached to, rather than target
, which is the element the event occurred on. For a button they will be the same, but TypeScript can only infer the actual element type for currentTarget
.
import * as React from "react";
const handleClick = ({ target, currentTarget }: React.MouseEvent<HTMLButtonElement>) => {
// target: EventTarget
// currentTarget: EventTarget & HTMLButtonElement
// ...other code goes here
}
const elt = <button onClick={handleClick} />
Upvotes: 8