React event types
The React event system is a wrapper around the browser’s native event system. TypeScript types for this event system are available in the
@types/react
npm package. These types can be used to strongly-type event parameters. Some of the common ones are:
ChangeEvent<T>
KeyboardEvent<T>
MouseEvent<T>
FormEvent<T>
These types are all derived from
SyntheticEvent<T>
.
All the event types are generic and take in the type for the element that raised the event. For example,
MouseEvent<HTMLButtonElement>
could be used for the parameter type for a button click handler.
Inline event handlers
If the event handler is implemented inline in the JSX element, it is automatically strongly-typed. Consider the example below:
<input
type="text"
value={criteria}
onChange={(e) =>
setCriteria(e.currentTarget.value)
TypeScript is able to infer the type of e
to be ChangeEvent<HTMLInputElement>
. So, we get nice autocompletion when we reference e
:
🏃 Play with the code
Named event handlers
The typing is a little more tricky when a named function is used for the event handler. Consider the example below:
function Searchbox() {
const [criteria, setCriteria] = React.useState(
const handleChange = (e) => { setCriteria(e.currentTarget.value); }; return (
<input
type="text"
value={criteria}
onChange={handleChange}
TypeScript infers the type of the e
parameter in handleChange
to be any
. So, no type checking will occur when e
is referenced in the handler implementation.
Not good!
We can use a type annotation to define the type of e
explicitly. What type should e
be set to? Well, a neat tip is to hover over the event handler prop to find out:
So, the type is ChangeEvent<HTMLInputElement>
. So, a strongly-typed version of the handleChange
event handler is as follows:
const handleChange = (
e: React.ChangeEvent<HTMLInputElement>) => {
setCriteria(e.currentTarget.value);
Neat!
🏃 Play with the code
Cross element event handlers
What about event handlers that handle events from multiple elements? Consider the example below:
const handleChange = (fieldName: string) => (e) => { ...};
return (
<input
type="text"
placeholder="Enter your name"
value={values.name}
onChange={handleChange("name")} />
<textarea
placeholder="Enter some notes"
value={values.notes}
onChange={handleChange("notes")} />
The e
parameter in the event handler is of type any
at the moment.
We can use the ChangeEvent
type for e
, but what element type do we pass into this generic type? The event handler is handling events for two different elements - HTMLInputElement
and HTMLTextAreaElement
. We can use the union type, HTMLInputElement | HTMLTextAreaElement
, for these elements. So, a strongly-typed event handler is as follows:
const handleChange = (fieldName: string) => (
e: React.ChangeEvent< HTMLInputElement | HTMLTextAreaElement >) => {
We can also narrow down the type for the fieldName
if we have a type for all the field values. In this example the type of values
is:
type NameAndNotes = {
name: string;
notes: string;
So, we can improve the typing of fieldName
with the keyof
keyword as follows:
const handleChange = (fieldName: keyof NameAndNotes) => ( ... ) => ...
Neat!