This guide shows how to use React with TypeScript, from a fresh project to typed props, state, and event handlers. TypeScript catches type mistakes before they reach the browser, and React's type definitions describe components and hooks out of the box.
The examples use TSX, the TypeScript version of JSX. If you know React but not TypeScript, the ideas map one to one: you add types without changing the component model. A later article covers how to type React props with TypeScript in depth.
Create a TypeScript React project
The fastest start is the Vite TypeScript template, which adds a TypeScript compiler and type definitions on top of the React template. Run the scaffold command:
npm create vite@latest my-app -- --template react-tsThe command creates a folder named my-app. Open it in your editor.
Files that contain JSX use the .tsx extension, and the template already includes the tsconfig files with the settings React needs. The build script runs tsc before Vite builds, so type errors stop the build.
If you prefer the plain JavaScript version first, the guide on creating a React app with Vite shows that path.
Type a component's props
Props are typed with an interface or an inline type. An interface reads well for a component with a few fields:
interface GreetingProps {
name: string;
}
function Greeting({ name }: GreetingProps) {
return <h1>Hello, {name}</h1>;
}If you pass a number to Greeting, the editor underlines it before you save. The type reports the mistake at write time instead of runtime, so it never reaches the browser.
Type state
useState infers the type from the initial value. A number stays a number, so setCount rejects anything else:
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>Count: {count}</button>;
}When a value can be one of several strings, the allowed values need to be explicit. Pass a type argument to useState inside the component to lock the union:
type Status = "idle" | "loading" | "ready";
const [status, setStatus] = useState<Status>("idle");Now setStatus only accepts those three strings.
Type event handlers
Events in React are typed with React.ChangeEvent and similar types from @types/react. The handler parameter needs the matching element type:
import { useState } from "react";
function Search() {
const [query, setQuery] = useState("");
function handleChange(event: React.ChangeEvent<HTMLInputElement>) {
setQuery(event.target.value);
}
return <input value={query} onChange={handleChange} aria-label="Search" />;
}The input updates query as you type, and the handler is fully typed. TypeScript knows event.target is the input element, so value is a string.
The aria-label gives the field an accessible name because it has no visible label beside it. The controlled input pattern itself is the same as the JavaScript version, with types added.
What to learn next
Type a few components in your own project and watch the editor catch mistakes before you save. As the project grows, the editor becomes a faster checker than the browser console, and type errors point at the exact file and line. Then read the props guide to cover optional fields, union props, and the children prop.
Rune AI
Key Insights
- Create a typed project with npm create vite@latest my-app -- --template react-ts.
- Use .tsx for files that contain JSX.
- Type props with an interface or inline type.
- useState infers types, or accepts an explicit type argument.
- Type events with React.ChangeEvent and the matching element type.
Frequently Asked Questions
Is TypeScript required for React?
What file extension do React TypeScript files use?
Do I need @types/react for a TypeScript React project?
Conclusion
TypeScript adds static types to React without changing the component model. Create a project from the react-ts template, type props with an interface, let useState infer or set explicit types, and type events with React.ChangeEvent.
More in this topic
How to Build a Dropdown Menu in React
Build a React dropdown menu with the ARIA menu button pattern. Handle open and close, keyboard arrows, and clicks outside the menu.
How to Animate React Components with Motion
Animate React components with the Motion library. Set up motion, add enter, hover, and exit animations, and respect reduced motion.
Headless UI Components Explained: Logic Without Locked Styling
Understand headless UI components and how libraries like Radix give you unstyled, accessible behavior that you style yourself.