Lesson 9 of 80
Typing a component is just typing a function — props are parameters, JSX is the return value. Everything from the last 8 lessons applies directly.
14 min read
Every option explains itself — why the right one is right, and why each wrong one is wrong. Miss one and it comes back later on a spaced-repetition schedule.
Question 1 of 3
const [user, setUser] = useState(null); later, setUser({ id: "1", name: "Ada" }) is rejected by TypeScript. Why?
Hints without spoilers, and a plain explanation of why a wrong answer was wrong — answered only from this lesson. Free account, no card.
Sign up freeWhat interviewers actually ask about this, and what a strong answer has to cover.
A strong answer covers
Likely follow-ups
From the React track: a component is just a function. From this track: typing a function means typing its parameters and its return value. Put together, there's nothing React-specific about typing a component — it's ordinary function typing, applied to props and JSX.
interface ButtonProps {
label: string;
onClick: () => void;
}
function Button({ label, onClick }: ButtonProps) {
return <button onClick={onClick}>{label}</button>;
}
ButtonProps is just an interface, the same as any other. The component is a function whose parameter happens to be props and whose return type happens to be JSX.
useState(null) gotchaconst [user, setUser] = useState(null);
// inferred type: null — not User | null
setUser({ id: "1", name: "Ada" }); // ❌ Argument of type 'User' is not assignable to 'null'
const [user2, setUser2] = useState<User | null>(null);
// explicit generic: user2 is User | null
setUser2({ id: "1", name: "Ada" }); // ✅
From the type-inference lesson: TypeScript infers from the value given. useState(null)'s only value is null itself — there's no other value to widen from — so the state's type is inferred as literally null, forever. The fix is the same generics mechanism from earlier in this track: supply useState's type parameter explicitly to tell it the full range of values this state can hold, not just its initial one.
function Button({ label, onClick }: { label: string; onClick: () => void }) — props typed directly on the destructured argument.
useState(null)'s inference gotcha is the exact widening behavior from the type-inference lesson, not something React-specific — there's simply no second value in useState(null)'s call for TypeScript to generalize from.function List<T>({ items, renderItem }: { items: T[]; renderItem: (item: T) => ReactNode }) types itself differently depending on what data it's actually given.Event — onClick: (e: React.MouseEvent<HTMLButtonElement>) => void gives you the actual properties (like e.currentTarget) typed correctly, where a looser type wouldn't.// @ts-ignore) from passing the wrong shape at runtime.Being asked to type a piece of React code is really a test of whether you've absorbed the last 8 lessons and can apply them somewhere concrete — generics, narrowing, inference, and structural typing all show up directly, not as separate "React TypeScript" rules to memorize on top.