TypeScript and React: Events
Web apps are really boring if you don’t interact with them. Events are key, and TypeScript’s React typings have great support for them.
In this section:
Basic Event Handling #
React uses its own event system. That’s why you can’t use typical MouseEvent
s or similar on your elements.
You need to use the specific React version, otherwise you get a compile error.
Luckily, React typings give you the proper equivalent of each event you might be familiar with from standard
DOM. They even have the same name, which can be tricky at times. You either need to be specific with e.g.
React.MouseEvent
or import the MouseEvent
typing right from the React module:
import React, { Component, MouseEvent } from 'react';
export class Button extends Component {
handleClick(event: MouseEvent) {
event.preventDefault();
alert(event.currentTarget.tagName); // alerts BUTTON
}
render() {
return <button onClick={this.handleClick}>
{this.props.children}
</button>
}
}
Events supported are: AnimationEvent
,
ChangeEvent
,
ClipboardEvent
,
CompositionEvent
,
DragEvent
,
FocusEvent
,
FormEvent
,
KeyboardEvent
,
MouseEvent
,
PointerEvent
,
TouchEvent
,
TransitionEvent
,
WheelEvent
. As well as SyntheticEvent
, for
all other events.
Restrictive Event Handling #
If you want to restrict your event handlers to specific elements, you can use a generic to be more specific:
import React, { Component, MouseEvent } from 'react';
export class Button extends Component {
/*
Here we restrict all handleClicks to be exclusively on
HTMLButton Elements
*/
handleClick(event: MouseEvent<HTMLButtonElement>) {
event.preventDefault();
alert(event.currentTarget.tagName); // alerts BUTTON
}
/*
Generics support union types. This event handler works on
HTMLButtonElement and HTMLAnchorElement (links).
*/
handleAnotherClick(event: MouseEvent<HTMLButtonElement | HTMLAnchorElement>) {
event.preventDefault();
alert('Yeah!');
}
render() {
return <button onClick={this.handleClick}>
{this.props.children}
</button>
}
}
All HTML element type definitions are in the default DOM typings of TypeScript. Don’t forget to add the
library dom
(see getting started).
Where’s InputEvent? #
If you come from Flow you will notice that InputEvent
(SyntheticInputEvent
respectively) is not supported by
TypeScript typings. This is mainly because InputEvent
is still an experimental interface and not fully
supported by all browsers. If you use the onInput
property from all input
elements, you will see that the interface for
onInput
uses any
for the event interface. This will change in the future.
To be a bit more specific in your code you can import SyntheticEvent
from the React typings.
import React, { Component, SyntheticEvent } from 'react';
export class Input extends Component {
handleInput(event: SyntheticEvent) {
event.preventDefault();
// ...
}
render() {
return <>
<input type="text" onInput={this.handleInput}/>
</>
}
}
Now you get at least some type safety.