← Back to TypeScript Course | Chapter 14: TypeScript with React | Lesson 3 of 8

Typing State

React state should have a predictable type so that updates remain safe. TypeScript can infer many state types automatically, while generic type parameters are useful for unions and complex initial values.

Basic useState Typing

Basic useState typing is inferred automatically from the initial value you pass in, so useState(0) already gives you a state variable typed as number without needing any manual annotation.

Example: Basic useState Typing

typescript
import React, { useState } from "react";

function Counter(): React.JSX.Element {
	const [count, setCount] = useState(0);
	return <p>{count}</p>;
}

export default Counter;

Explicit State Types

An explicit type argument to useState<T>() is needed when the initial value doesn't fully describe the type you actually want — for example when the state can later hold one of several different shapes.

Example: Explicit State Types

typescript
import React, { useState } from "react";

type Status = "idle" | "loading" | "done";

function Loader(): React.JSX.Element {
	const [status, setStatus] = useState<Status>("idle");
	return <p>{status}</p>;
}

export default Loader;

Nullable State

Nullable state is typed explicitly as useState<User | null>(null), which forces every place that reads the state to first check it isn't null before accessing a property on the expected object.

Example: Nullable State

typescript
import React, { useState } from "react";

interface User {
	name: string;
}

function Profile(): React.JSX.Element {
	const [user, setUser] = useState<User | null>(null);
	return <p>{user ? user.name : "No user"}</p>;
}

export default Profile;

Array State

Array state benefits from an explicit type argument like useState<Item[]>([]), since an empty array alone gives TypeScript no information about what type of items the array is meant to eventually hold.

Example: Array State

typescript
import React, { useState } from "react";

interface Item {
	id: number;
	label: string;
}

function List(): React.JSX.Element {
	const [items, setItems] = useState<Item[]>([]);
	return <p>{items.length} items</p>;
}

export default List;

State with Functional Updates

Functional updates — setState(prev => ...) — automatically type the prev parameter as the state's current type, letting you safely compute a new value from the previous one without re-declaring the type by hand.

Example: State with Functional Updates

typescript
import React, { useState } from "react";

function Counter(): React.JSX.Element {
	const [count, setCount] = useState(0);
	const increment = () => setCount((prev) => prev + 1);
	return <button onClick={increment}>{count}</button>;
}

export default Counter;
🔒

Chapter Quiz — Complete all 8 topics to unlock

0/8 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.