Typing Events & Refs in TypeScript
Use React.ChangeEvent, React.MouseEvent, and RefObject generics for DOM interactions.
Typing Events & Refs in TypeScript is a free React Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the React Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
React Synthetic Events
React wraps native DOM events in SyntheticEvent. Each event type has a specific generic: React.ChangeEvent<HTMLInputElement>, React.MouseEvent<HTMLButtonElement>, etc.
Typing onChange
The most common event is onChange on inputs. Type its handler with React.ChangeEvent<HTMLInputElement>.
function SearchInput() {
const [value, setValue] = useState('');
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setValue(e.target.value);
};
return <input value={value} onChange={handleChange} />;
}Typing onClick
Button clicks use React.MouseEvent<HTMLButtonElement>. Access e.currentTarget, e.preventDefault(), and e.stopPropagation() with full typing.
function DeleteButton({ onDelete }: { onDelete: () => void }) {
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
e.stopPropagation();
onDelete();
};
return <button onClick={handleClick}>Delete</button>;
}Typing onSubmit
Form submission uses React.FormEvent<HTMLFormElement>. Always call e.preventDefault() to stop the default browser navigation.
function LoginForm() {
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
const form = e.currentTarget;
const email = (form.elements.namedItem('email') as HTMLInputElement).value;
console.log(email);
};
return (
<form onSubmit={handleSubmit}>
<input name="email" />
<button type="submit">Login</button>
</form>
);
}Typing Keyboard Events
Use React.KeyboardEvent<HTMLElement> to type keyboard handlers. Access e.key, e.code, and e.ctrlKey safely.
function CommandInput() {
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter' && e.metaKey) {
submitCommand();
}
};
return <input onKeyDown={handleKeyDown} />;
}useRef for DOM Elements
Pass the HTML element type as the generic to useRef and initialize to null. TypeScript then knows the ref holds that element type.
function AutoFocusInput() {
const inputRef = useRef<HTMLInputElement>(null);
useEffect(() => {
inputRef.current?.focus();
}, []);
return <input ref={inputRef} />;
}Mutable Ref vs DOM Ref
When storing a mutable value (not a DOM node), initialize useRef with a value instead of null. TypeScript infers a mutable MutableRefObject.
// DOM ref (read-only current)
const divRef = useRef<HTMLDivElement>(null);
// Mutable ref (read-write current)
const countRef = useRef<number>(0);
countRef.current += 1; // ✓ no TypeScript errorTyping useImperativeHandle
When exposing a ref API from a child component, define an interface for the handle and use it in both forwardRef and useImperativeHandle.
interface DialogHandle {
open: () => void;
close: () => void;
}
const Dialog = forwardRef<DialogHandle, { title: string }>((props, ref) => {
useImperativeHandle(ref, () => ({
open: () => console.log('open'),
close: () => console.log('close'),
}));
return <div>{props.title}</div>;
});Ref Callbacks
A ref callback receives the DOM element or null. Type it as (node: HTMLElement | null) => void.
function MeasureDiv() {
const [height, setHeight] = useState(0);
const measuredRef = (node: HTMLDivElement | null) => {
if (node) setHeight(node.getBoundingClientRect().height);
};
return <div ref={measuredRef}>Content: {height}px tall</div>;
}Event Target vs Current Target
e.target is the element that triggered the event; e.currentTarget is the element the handler is attached to. Cast e.target when you need specific properties.
const handleClick = (e: React.MouseEvent<HTMLUListElement>) => {
const target = e.target as HTMLLIElement;
console.log(target.dataset.id);
};Generic Event Handler Type
To write reusable event handler functions, use the generic React.EventHandler<Event> or just write the full function signature inline.
type InputChangeHandler = React.ChangeEventHandler<HTMLInputElement>;
const logChange: InputChangeHandler = (e) => {
console.log(e.target.value); // e is fully typed
};Quick Check
Which TypeScript type should you use for a useRef that holds an HTMLInputElement?
Recap
Type event handlers with React.ChangeEvent, React.MouseEvent, and React.FormEvent generics. Type DOM refs with useRef<HTMLElement>(null) and mutable refs with the value type. Use forwardRef with an explicit handle interface for imperative APIs.
Frequently asked questions
Is the “Typing Events & Refs in TypeScript” lesson free?
Yes — the full text of “Typing Events & Refs in TypeScript” is free to read here on the web, and the React Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the React Academy course, upgrade to CoddyKit PRO.
What will I learn in “Typing Events & Refs in TypeScript”?
Use React.ChangeEvent, React.MouseEvent, and RefObject generics for DOM interactions. You practise React Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start React Academy?
No prior experience is required. React Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Typing Events & Refs in TypeScript” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this React Academy lesson?
Yes. Every React Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Typing Props & Component Return Types
- Typing Events & Refs in TypeScript
- Generic Components & Utility Types
- Typing Context & Custom Hooks