How to Type React Events and Form Handlers

Type React events and form handlers with the event types from @types/react. Most handlers infer the type, and you annotate only when extracting functions.

5 min read

To type React events and form handlers, use the event types from @types/react, such as ChangeEvent for inputs and FormEvent for forms. Inline handlers infer the event type automatically, so you only annotate when you extract a function into a separate declaration. The annotations are small and follow one predictable pattern, so they are easy to remember.

Let inference do the work

Install @types/react and @types/react-dom as dev dependencies, and use the .tsx extension for any file that contains JSX. Inline handlers then need no annotation, because the prop tells TypeScript which event it is.

App.tsxApp.tsx
import { useState } from "react";
 
function NameField() {
  const [name, setName] = useState("");
  return <input value={name} onChange={(e) => setName(e.target.value)} />;
}

The onChange prop types e as the change event for an input, so e.target.value type-checks without any work. Most small components never need an explicit event type.

Type an extracted handler

When the handler moves into its own function, the event no longer has a prop to infer from. Annotate it with React.ChangeEvent and the element type.

App.tsxApp.tsx
function handleChange(event: React.ChangeEvent<HTMLInputElement>) {
  setName(event.currentTarget.value);
}

The generic names the element the event fires on, so TypeScript knows the handler is for a text input. The same pattern covers textarea, select, and other editable elements.

Common event types

Four types cover most handlers.

  • ChangeEvent for input and select edits.
  • FormEvent for form submission.
  • MouseEvent for clicks.
  • KeyboardEvent for key presses.

Each takes the element as a type argument, as shown in the examples above. Every one extends React.SyntheticEvent, the shared base type. You can import them directly with import type { ChangeEvent } from "react", which reads shorter in files that use many types, and the full set lives in the @types/react definitions.

Read currentTarget for the typed element

event.currentTarget is typed as the element the handler is attached to, while event.target is a generic EventTarget. Reading currentTarget gives you the value without a cast.

App.tsxApp.tsx
function handleChange(event: React.ChangeEvent<HTMLInputElement>) {
  setName(event.currentTarget.value);
}

In most React handlers currentTarget is exactly the element you want. A change handler shared by several fields can read currentTarget to get the field's value and its name attribute to tell the fields apart. Reserve target for cases where the event bubbles from a child and you need the original source.

Type a form submit handler

A form's onSubmit receives FormEvent with the form element type. preventDefault and FormData both work on currentTarget.

App.tsxApp.tsx
function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
  event.preventDefault();
  const data = new FormData(event.currentTarget);
  const email = data.get("email");
}

The handler stops the reload and reads named fields from the submitted form. The generic ties the event to HTMLFormElement, so currentTarget is a form with all its methods.

What to learn next

The same typing ideas extend to typing component props and the events overview, which covers the runtime side of these handlers.

Rune AI

Rune AI

Key Insights

⚠ This article has a formatting issue and may not display correctly.

Our team has been notified. The content is shown as plain text below.

- Inline handlers infer the event type automatically. - Annotate extracted handlers with React.ChangeEvent or similar. - Use currentTarget for the typed element. - Form submit handlers use React.FormEvent. - Files with JSX use the .tsx extension.
RunePowered by Rune AI

Frequently Asked Questions

Do I need to type inline event handlers?

No. TypeScript infers the event type from the prop, so an inline onChange handler already knows the event is a ChangeEvent for that element.

Why use currentTarget instead of target?

currentTarget is typed as the element the handler is attached to, while target is a generic EventTarget. currentTarget gives you the element's value without a cast.

What type do I use for a form submit handler?

Use React.FormEvent<HTMLFormElement>, or FormEvent<HTMLFormElement> if you import the type from react.

Conclusion

⚠ This article has a formatting issue and may not display correctly.

Our team has been notified. The content is shown as plain text below.

Inline handlers infer their event types, and extracted handlers get an annotation like ChangeEvent. Read currentTarget for the typed element and FormEvent for forms.