React - TypeScript with React
Overview
Estimated time: 25–35 minutes
Add type safety to your components, props, events, state, and reducers using TypeScript. We compile TS in-browser with Babel.
Prerequisites
- Basic TypeScript (interfaces, unions, generics) helpful but not required.
Try it: Typed Props and Events
View source
type GreetingProps = { name: string };
function Greeting({ name }: GreetingProps){
return <h3>Hello, {name}!</h3>;
}
function App(){
const [text, setText] = React.useState('');
function onChange(e: React.ChangeEvent){
setText(e.target.value);
}
return (
<div>
<Greeting name={text || 'World'} />
<input value={text} onChange={onChange} placeholder="Type your name" />
</div>
);
}
ReactDOM.createRoot(document.getElementById('try-ts')).render(<App />);
Try it: Typed Reducer
View source
type State = { count: number };
type Action = { type: 'inc'; step: number } | { type: 'reset'; to: number };
function reducer(s: State, a: Action): State {
switch (a.type){
case 'inc': return { count: s.count + a.step };
case 'reset': return { count: a.to };
}
}
function Counter(){
const [state, dispatch] = React.useReducer(reducer, { count: 0 });
return (
<div>
Count: {state.count}
<button onClick={() => dispatch({type:'inc', step:1})}>+1</button>
<button onClick={() => dispatch({type:'reset', to:0})} style={{marginLeft:8}}>Reset</button>
</div>
);
}
ReactDOM.createRoot(document.getElementById('try-ts-2')).render(<Counter />);
Syntax primer
- Props:
type Props = { ... }
and destructure in component signature. - Events:
React.ChangeEvent<HTMLInputElement>
for inputs. - State:
useState<T>()
generics; reducers with typedState
andAction
.
Common pitfalls
- Using
any
everywhere defeats TypeScript’s benefits—prefer precise types. - Overly complex generics reduce readability; start simple, refine later.
Checks for Understanding
- How do you type an input change handler in React + TypeScript?
- What are the benefits of typed reducers?
Show answers
(e: React.ChangeEvent<HTMLInputElement>)
captures event typing for inputs.- They prevent invalid actions/state and improve maintainability through explicit types.
Exercises
- Define a
User
interface and type a component that renders a user card. - Add a discriminated union to the reducer and handle a new action.
- Introduce a typed Context for configuration and consume it in a component.