React with TypeScript
Add types to your components, props, state and events — the way nearly every modern React job writes code.
What you will learn
- Type a component’s props with an interface
- Type useState and event handlers
- Read the errors TypeScript gives you
Why type your React?
You met TypeScript in its own module — JavaScript with types, little labels that say what kind of value something is (a number, a string, an object of a certain shape). React projects use TypeScript to catch mistakes before the app runs: passing the wrong prop, reading a field that does not exist, or forgetting a required value. In a real React job, the files are usually .tsx (TypeScript + JSX) rather than .jsx.
The good news: it is the same React you already know. You just add type labels in a few places — to props, to state, and to event handlers. Let us see each one.
Typing props with an interface
An interface is a named description of an object’s shape — which fields it has and what type each one is. We describe what props a component expects, then attach that interface to the component. This snippet runs in a real Vite + TypeScript project, so it is shown as code with its Output.
// Greeting.tsx
interface GreetingProps {
name: string;
age: number;
isStudent?: boolean; // the ? means optional
}
function Greeting({ name, age, isStudent }: GreetingProps) {
return (
<div>
<h3>Hello, {name}!</h3>
<p>Age: {age}{isStudent ? ' (student)' : ''}</p>
</div>
);
}
// Using it:
// <Greeting name="Asha" age={20} isStudent /> ok
// <Greeting name="Ravi" /> ERROR: 'age' is missingReading it piece by piece:
- The
interface GreetingPropsblock lists the three props and their types:nameis astring,ageis anumber, andisStudentis an optionalboolean(the?after its name means “you may leave this out”). - We attach the interface to the component’s parameter:
function Greeting({ name, age, isStudent }: GreetingProps). The: GreetingPropspart says “these props must match that shape”. - Now the editor helps you.
<Greeting name="Asha" age={20} isStudent />is fine. But<Greeting name="Ravi" />shows a red error before you ever run the app, because the requiredageprop is missing.
Note: Output (the error TypeScript shows for the bad usage): Property 'age' is missing in type '{ name: string; }' but required in type 'GreetingProps'. The mistake is caught while you type — not by a confused user later.
Typing useState
Most of the time TypeScript can figure out the type of state by itself. When it cannot (an empty list, or a value that might be missing), you tell it with angle brackets useState<Type>(...).
const [count, setCount] = useState(0); // inferred as number
const [name, setName] = useState(''); // inferred as string
// When the type is not obvious, write it yourself:
interface User { id: number; name: string; }
const [users, setUsers] = useState<User[]>([]); // a list of User, starts empty
const [user, setUser] = useState<User | null>(null); // a User, or nothing yetWalking through it: for useState(0) TypeScript sees the 0 and decides count is a number — no extra work needed. But useState([]) is an empty array; TypeScript cannot guess what goes in it, so we write useState<User[]>([]) to say “a list of User objects, currently empty”. The User | null form (a union type, meaning “one of these”) is the standard way to say “we do not have the user yet, but we will”.
Typing event handlers
When you handle an event like typing in an input, the event object e has a type. TypeScript ships the right type for each event so e.target.value autocompletes correctly.
function SearchBox() {
const [text, setText] = useState('');
function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
setText(e.target.value); // .value is known to be a string
}
return <input value={text} onChange={handleChange} placeholder="Search" />;
}The label e: React.ChangeEvent<HTMLInputElement> tells TypeScript “this is a change event coming from an <input>”. Because of that, e.target.value is known to be a string and the editor autocompletes it. If you instead read e.target.valeu (a typo) or expected a number, TypeScript would flag it immediately. You rarely memorise these event types — you start typing React. and the editor suggests the right one.
Note: Common event types worth recognising:
• React.ChangeEvent<HTMLInputElement> — typing in a text input
• React.FormEvent<HTMLFormElement> — submitting a form
• React.MouseEvent<HTMLButtonElement> — clicking a button
Tip: Start a project with TypeScript from day one: npm create vite@latest my-app -- --template react-ts. The -ts template gives you .tsx files and type-checking out of the box.
Watch out: Do not reach for the any type to “make the error go away”. any switches off all checking for that value and hides the very bugs TypeScript is meant to catch. Prefer a proper interface or a union type.
Q. How do you describe the shape of a component’s props in TypeScript?
✍️ Practice
- Write a
ProductCardPropsinterface (name: string, price: number, inStock?: boolean) and type aProductCardcomponent with it. - Type a
useStatethat holds a list of objects, starting empty.
🏠 Homework
- Convert one earlier
.jsxcomponent to.tsx: add a props interface, type its state, and type one event handler.