BeCuriouzBeCuriouz

Learn something new every day

🔷 TypeScript
⚛️

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:

tsx
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:

tsx
const [count, setCount] = useState(0);           // number, inferred
const [user, setUser] = useState<User | null>(null); // must be explicit

Other hooks follow the same rule. useRef(null) 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.

⚛️ Typing React Components: Props, State, and Hooks — BeCuriouz