Typing Component Props, Events, and Hooks
TypeScript really shines in React when working with component props, events, and hooks like useState
or useEffect
. Here’s how to type them properly so you get type safety and helpful autocompletions.
Typing Component Props
interface Todo {
title: string;
done: boolean;
}
interface TodoItemProps {
todo: Todo;
onToggle: (title: string) => void;
}
const TodoItem: React.FC<TodoItemProps> = ({ todo, onToggle }) => (
<div>
<input
type="checkbox"
checked={todo.done}
onChange={() => onToggle(todo.title)}
/>
{todo.title}
</div>
);
💡 Tip: Try it in your IDE!With typed props, you’ll get autocompletion and instant feedback — making mistakes harder and coding faster.
Typing useState
Step 1: Create the state type
interface Todo {
title: string;
done: boolean;
}
Step 2: Type the useState hook
// empty initial state
const [todos, setTodos] = useState<Todo[]>([]);
const INITIAL_TODO: Todo[] = [
{
title: "first task",
done: false,
},
{
title: "second task",
done: true,
},
{
title: "third task",
done: true,
},
];
const [todos, setTodos] = useState<Todo[]>(INITIAL_TODO);
Now todos
is typed as an array of Todo
objects, and setTodos
will only accept that type.
Step 3: Using setTodos
Here are three valid and clean ways to use setTodos
:
// 1. Basic usage — straightforward and readable
setTodos([{ title: "new todo", done: false }]);
// 2. Callback form — preferred if referencing previous state or writing multiple lines
setTodos((prevTodos) => {
return [...prevTodos, { title: "new todo", done: false }];
});
// 3. One-liner callback — clean if short
setTodos((prev) => [...prev, { title: "new todo", done: false }]);
🧠 Why use thecallback
form?React batches updates — using the
callback
ensures you’re working with the most recent state, especially insideuseEffect
or async operations.
Typing Events
React’s synthetic events are strongly typed too. Here’s an example with an input change handler:
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
console.log(e.target.value);
};
Typing Custom Hooks
If you create your own hooks, type the input and output clearly:
function useTodoList(): [Todo[], (todo: Todo) => void] {
const [todos, setTodos] = useState<Todo[]>([]);
const addTodo = (todo: Todo) => setTodos((prev) => [...prev, todo]);
return [todos, addTodo];
}
const [todos, addTodo] = useTodoList();
addTodo({ title: "Learn TS", done: false });
Last updated