Using React with TypeScript
In this page:
Typing Component Props
Defining an interface (or type alias) describing a component's expected props, then using it as the type for the props parameter, lets TypeScript catch mistakes like a missing required prop or a value of the wrong type at compile time, before the code ever runs.
Note: Name the props interface after the component with a Props suffix, like GreetingProps for a Greeting component.
Warning: Typing props as any (or skipping types entirely) gives up all of TypeScript's benefit for that component — it's essentially back to plain JavaScript.
Example: Typing Component Props
// Run in your local React project (npm install required)
interface GreetingProps {
name: string;
age?: number; // optional
}
function Greeting({ name, age }: GreetingProps) {
return <p>Hello, {name}{age ? ` (${age})` : ''}</p>;
}
Typing useState
TypeScript usually infers a useState hook's type automatically from its initial value, like useState(0) being inferred as number. When the initial value doesn't fully capture the intended type (like an empty array that will later hold strings), you specify the type explicitly with a generic.
Note: useState<string[]>([]) is a common pattern — TypeScript can't infer 'array of strings' from an empty array alone.
Warning: Without an explicit generic, useState([]) infers the type as never[], which then rejects any actual items you try to add later.
Example: Typing useState
// Run in your local React project (npm install required)
function TodoList() {
const [todos, setTodos] = useState<string[]>([]);
const addTodo = (text: string) => setTodos([...todos, text]);
return <button onClick={() => addTodo('New task')}>Add ({todos.length})</button>;
}
Typing Event Handlers
React's built-in TypeScript types include specific event types, like React.ChangeEvent<HTMLInputElement> for an input's onChange handler, giving you correct autocomplete and type-checking on properties like event.target.value.
Note: Let your editor's autocomplete suggest the exact event type for a given JSX event prop — you rarely need to memorize them all.
Warning: Using a generic any or the wrong specific event type (like using a button's event type on an input) can hide real type errors related to which properties actually exist on that event.
Example: Typing Event Handlers
// Run in your local React project (npm install required)
function SearchBox() {
const [query, setQuery] = useState('');
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setQuery(e.target.value);
};
return <input value={query} onChange={handleChange} />;
}
- Typing a component's props as any, which defeats the entire purpose of adding TypeScript.
- Forgetting the React import needed for JSX.Element or React.FC return types in some TS configurations.
- Not typing useState's generic when the initial value doesn't clearly imply the full type (like starting a list with an empty array).
- TypeScript adds static type-checking to React, catching many prop/state mismatches before runtime.
- A component's props are typically typed with an interface or type alias for its props object.
- useState<Type>(initialValue) lets you specify a hook's type explicitly when it can't be inferred correctly.
- TypeScript integrates directly into React's existing patterns — components, hooks, and props all get typed, not replaced.
Requires a TypeScript-aware build setup (Vite/Next.js templates support it out of the box); works with any React version.
Chapter Quiz — Complete all 14 topics to unlock
0/14 topics done
Complete these topics first:
- Error Boundaries
- React Portals
- Modals using Portals (practical use)
- React Suspense
- Code Splitting with React.lazy
- Introduction to Server Components
- Introduction to Next.js (server-side React)
- Using React with TypeScript
- Scalable Folder Architecture
- Common React Design Patterns
- Component Documentation with Storybook
- Accessibility (a11y) in React
- i18n with react-i18next
- React Security Best Practices