cover image
Web

Event Typings of React with TypeScript

Discover how to enhance your React components with type safety using TypeScript typings for events. TypeScript, a powerful superset of JavaScript, allows you to catch errors early and improve code clarity. Delve into browser events and their role in notifying applications of user or browser-triggered changes. Explore the world of React events and learn how to handle them effectively with TypeScript, enabling seamless integration of event typings for better tooling support and reliability.

React in TypeScript

React is a JavaScript library that enables software developers to write components with code and markup. TypeScript is a superset of JavaScript that adds type annotations to variables, functions, and objects. React can be used with TypeScript to create type-safe components. Using TypeScript is especially recommended for larger projects because it helps to avoid bugs and makes the code easier to understand.

You can install the React typings in TypeScript with the following command:

npm install @types/react --save-dev

Let us take a look at the typings for React using the JavaScript browser events.

JavaScript Browser Events

In JavaScript in the browser, events are fired to notify the application of "interesting changes". These changes can be triggered by the user, such as clicking a button, or by the browser, such as the page loading or an error occurring. But events can also be server sent events or events from workers.

Since we are focused on React in this article, we are mainly concerned with the events that are triggered by the user in the browser.

React Events

React facilitates the handling of events in the browser. The event handlers are functions that are called when the event occurs.

This is an example of handling a keyboard event in React:

const KeyboardEventExample = () => {
 const onKeyPress = (event) => {
   console.log(event.key);
 }; 

 return (
    <input type="text" onKeyPress={onKeyPress} />
  );
};

In this example, the onKeyPress function is called when the user presses a key on the keyboard. The event object is passed to the function as an argument. The event object contains information about the event, such as the key that was pressed.

TypeScript React Event Typings

The same KeyboardEventExample in TypeScript looks like this:

import React from 'react';

const KeyboardEventExample: React.FC = () => {
  const onKeyPress = (event: React.KeyboardEvent<HTMLInputElement>) => {
    console.log(event.key);
  };

  return (
    <input type="text" onKeyPress={onKeyPress} />
  );
};

The React.FC is the type definition of a function component. In our case it has no props.

In the index.d.ts file of the @types/react package, the React.FC is defined as follows:

type FC<P = {}> = FunctionComponent<P>;

interface FunctionComponent<P = {}> {
    (props: P, context?: any): ReactElement<any, any> | null;
    propTypes?: WeakValidationMap<P> | undefined;
    contextTypes?: ValidationMap<any> | undefined;
    defaultProps?: Partial<P> | undefined;
    displayName?: string | undefined;
}

The type signature of the onKeyPress function is React.KeyboardEvent<HTMLInputElement>. This means that the function takes an event object as an argument that is of type React.KeyboardEvent<HTMLInputElement>. The React.KeyboardEvent is a generic type that takes the type of the target element as a type argument. In our case, the target element is an HTMLInputElement because we use the <input> element.

The React.KeyboardEvent is defined in the index.d.ts file of the @types/react package as follows:

export type ModifierKey = "Alt" | "AltGraph" | "CapsLock" | "Control" | "Fn" | "FnLock" | "Hyper" | "Meta" | "NumLock" | "ScrollLock" | "Shift" | "Super" | "Symbol" | "SymbolLock";

interface KeyboardEvent<T = Element> extends UIEvent<T, NativeKeyboardEvent> {
    altKey: boolean;
    /** @deprecated */
    charCode: number;
    ctrlKey: boolean;
    code: string;
    /**
     * See [DOM Level 3 Events spec](https://www.w3.org/TR/uievents-key/#keys-modifier). for a list of valid (case-sensitive) arguments to this method.
     */
    getModifierState(key: ModifierKey): boolean;
    /**
     * See the [DOM Level 3 Events spec](https://www.w3.org/TR/uievents-key/#named-key-attribute-values). for possible values
     */
    key: string;
    /** @deprecated */
    keyCode: number;
    locale: string;
    location: number;
    metaKey: boolean;
    repeat: boolean;
    shiftKey: boolean;
    /** @deprecated */
    which: number;
}

The provided type definition in TypeScript is for the KeyboardEvent interface, which extends the UIEvent interface and adds additional properties and methods specific to keyboard events.

KeyboardEvent uses generics and can thus be applied to all elements. The type of the target element is passed as a type argument. In our case, the target element is an HTMLInputElement because we use the <input> element.

The other properties and methods of the KeyboardEvent are specific to keyboard events.

All UI events are derived from one base class, the BaseSyntheticEvent:

interface BaseSyntheticEvent<E = object, C = any, T = any> {
    nativeEvent: E;
    currentTarget: C;
    target: T;
    bubbles: boolean;
    cancelable: boolean;
    defaultPrevented: boolean;
    eventPhase: number;
    isTrusted: boolean;
    preventDefault(): void;
    isDefaultPrevented(): boolean;
    stopPropagation(): void;
    isPropagationStopped(): boolean;
    persist(): void;
    timeStamp: number;
    type: string;
}

This BaseSyntheticEvent has the basic properties and methods that all UI events have in common, like if the event is bubbling, if the event is cancelable, if the default action is prevented, and so on.

Thus, you can see when leveraging TypeScript in your React project, you can easily see the type of the event object and the properties and methods it provides.

These types also help most IDEs that support TypeScript, like Visual Studio Code, to aid you in crafting your code.

Conclusion

I hope that by reading this article, you could learn more about the event typings of React with TypeScript. It is worth taking a look behind the scenes of React and TypeScript to understand how they work together. When you import the TypeScript React typings, you can simply look in your node_modules folder and @types/react/index.d.ts and @types/react/global.d.ts to see the type definitions.

References

  • React: https://react.dev

  • TypeScript: https://www.typescriptlang.org

  • React event handlers: https://react.dev/reference/react-dom/components/common#event-handler

  • MDN events: https://developer.mozilla.org/en-US/docs/Web/Events

Photo by Dominik Martin on Unsplash

Published 30 Jul 2023
Thomas Derflinger

Written by Thomas Derflinger

I am a visionary entrepreneur and software developer. In this blog I mainly write about web programming and related topics like IoT.