thecodex.expert · The Codex Family of Knowledge
TypeScript

TypeScript with React

Passing the wrong prop to a component, or forgetting a required one, is caught at compile time — not discovered when a user hits a blank screen in production.

TypeScript 6.0 .tsx extension Last verified:
Canonical Definition

A React file containing JSX must use the .tsx extension (rather than plain .ts), so the compiler knows to parse JSX syntax. A component's props are typically typed with an interface or type alias, and destructured directly in the function signature. Hooks are generic: useState<T> can have its type parameter given explicitly or inferred from the initial value passed in.

Typing component props

A missing required prop, or a prop of the wrong type, is a compile error at every call site — caught long before the component ever renders in a browser.

TypeScriptGreeting.tsx
interface GreetingProps {
    name: string;
    excited?: boolean;   // optional prop
}

function Greeting({ name, excited = false }: GreetingProps) {
    return <div>{excited ? `Hi ${name}!!!` : `Hello, ${name}`}</div>;
}

<Greeting name="Alice" />;          // fine
<Greeting name="Bob" excited />;    // fine
// <Greeting />;                    // COMPILE ERROR: missing required prop 'name'

Typing useState and useEffect

useState infers its type from the initial value when possible; an explicit type argument is needed when the state can be a union that isn't obvious from the initializer alone, like a value that starts as null.

TypeScriptUserProfile.tsx
interface User { name: string; }

function UserProfile() {
    const [count, setCount] = useState(0);              // inferred: number
    const [user, setUser] = useState<User | null>(null); // explicit: needed since null alone infers only null

    useEffect(() => {
        fetchUser().then(setUser);
    }, []);

    return user ? <p>{user.name}</p> : <p>Loading...</p>;
}

Typing event handlers

React's own type definitions provide specific event types (React.ChangeEvent<HTMLInputElement>, etc.), giving full autocomplete on the event object rather than treating it as untyped.

TypeScriptSearchInput.tsx
function SearchInput() {
    const [query, setQuery] = useState("");

    function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
        setQuery(e.target.value);   // e.target correctly typed as HTMLInputElement
    }

    return <input value={query} onChange={handleChange} />;
}

Sources

1
Microsoft. TypeScript Handbook, "JSX", typescriptlang.org/docs/handbook/jsx.html, and the React TypeScript Cheatsheet (community-maintained, endorsed by the React docs).