BeCuriouzLearn something new every day
Typing React Components: Props, State, and Hooks
💡 Let TypeScript infer props and state from values, but supply an explicit generic to useState/useRef whenever the initial value is narrower than what the variable will hold.
React components are just functions, so typing them starts with typing their input. A component's props become a typed parameter — usually an interface or type. React infers the return type, so you rarely annotate it yourself:
interface GreetingProps {
name: string;
count?: number; // optional prop
}
function Greeting({ name, count = 0 }: GreetingProps) {
return <h1>Hello {name}, seen {count} times</h1>;
}State via useState is where inference shines — and sometimes fails. useState(0) infers number and useState('') infers string, so you write nothing. But useState(null) infers null forever, and you can never store a user object in it. When the initial value doesn't describe every future value, pass the type explicitly with a generic argument:
const [count, setCount] = useState(0); // number, inferred
const [user, setUser] = useState<User | null>(null); // must be explicitOther hooks follow the same rule. useRef types a DOM ref so ref.current is HTMLInputElement | null. useReducer infers state and action from your reducer function. For children, use the built-in React.ReactNode type, which covers strings, elements, arrays, and null — the widest sensible type for anything React can render. The guiding principle: let inference do the work, and reach for an explicit generic only when the initial value is narrower than the values the variable will eventually hold.