Common React TypeScript Errors and How to Fix Them

Fix frequent React TypeScript errors: missing prop types, wrong event handlers, useRef null types, and the React 19 JSX namespace.

6 min read

Most React TypeScript errors come from a missing or wrong type in one of three places: props, event handlers, and refs. React 19 also moved the JSX namespace, which produces its own error. Each has a small, specific fix, and the compiler message usually names the exact place.

Missing props types

Without a props type, TypeScript cannot know what a component accepts. It reports that the parameter has an implicit any type, or that a property does not exist on an empty object type.

App.tsxApp.tsx
interface ButtonProps {
  label: string;
}
 
export default function Button({ label }: ButtonProps) {
  return <button>{label}</button>;
}

Annotating the parameter with ButtonProps fixes both messages, and passing a wrong prop now fails at the call site instead of inside the component. The interface keeps the component's contract in one place, so the error and its fix sit next to each other. See how to type React props with TypeScript for the full patterns.

Wrong event handler types

An inline handler often gets an implicit any event, which hides typos and loses autocomplete. Type the event with the matching React event type.

App.tsxApp.tsx
import type { ChangeEvent } from "react";
 
export default function NameInput() {
  function handleChange(event: ChangeEvent<HTMLInputElement>) {
    console.log(event.target.value);
  }
 
  return <input onChange={handleChange} />;
}

The ChangeEvent type, parameterized with the input element, gives event.target the correct value type, so reading value no longer errors. See how to type React events and form handlers.

useRef and null

A ref typed for an input element starts as null, so its current property is the element or null and TypeScript forces a guard. React 19 also requires useRef to receive an argument.

App.tsxApp.tsx
import { useRef } from "react";
 
export default function FocusInput() {
  const ref = useRef<HTMLInputElement>(null);
 
  function focus() {
    ref.current?.focus();
  }
 
  return (
    <>
      <input ref={ref} />
      <button onClick={focus}>Focus</button>
    </>
  );
}

The optional chaining on ref.current satisfies the null check. In React 19, refs are always mutable and useRef(undefined) returns a ref typed as the element or undefined, so a guard is still required before reading it.

The JSX namespace moved

The React 19 types removed the global JSX namespace in favor of React.JSX. Replace JSX.Element with React.JSX.Element.

App.tsxApp.tsx
function render(): React.JSX.Element {
  return <p>Hello</p>;
}

If you augment JSX for custom elements, wrap the augmentation in declare module "react" and use the module specifier your tsconfig JSX runtime expects. Older code that references the global JSX namespace breaks after the type upgrade.

Object is possibly null

TypeScript also flags a possibly null value when you use it without checking, which happens often with DOM elements and array lookups. Guard the value with an if statement or optional chaining before accessing its properties, and the error clears without a type assertion or any.

Verify the fix

Run the TypeScript compiler or the editor diagnostics after each fix and confirm the error clears. Most of these errors disappear with one precise annotation rather than a broad any, and that annotation documents the component for the next reader.

Rune AI

Rune AI

Key Insights

  • Type props with an interface or type alias.
  • Use React.ChangeEvent and React.MouseEvent for handlers.
  • Guard ref.current because it can be null.
  • Replace JSX.Element with React.JSX.Element.
  • Prefer one precise annotation over any.
RunePowered by Rune AI

Frequently Asked Questions

Why did JSX.Element stop working after upgrading to React 19?

The React 19 types removed the global JSX namespace in favor of React.JSX. Replace JSX.Element with React.JSX.Element.

Why does useRef(null) complain about being read-only?

React 19 made refs always mutable and requires useRef to receive an argument. Use useRef(undefined) or a typed initial value, and guard current before using it.

Conclusion

React TypeScript errors usually come from a missing props type, a wrong event type, an unguarded ref, or the moved JSX namespace. Each has one precise annotation as the fix.