Skip to main content

How to type useCallback()?

Basic syntax

javascript
const callback = useCallback(() => { // ... }, []);

useCallback returns a memoized function whose type depends on its body. TypeScript infers the type automatically if everything is declared explicitly.


TypeScript infers the type itself when the parameters and return value are specified inside:

javascript
const handleClick = useCallback((id: number) => { console.log(id); }, []);

The type here is:

javascript
(id: number) => void

Recommendation: don't duplicate the typing outside if TypeScript can infer it itself.


2. Specifying the type explicitly (for example, for callbacks in props)

Sometimes you need the callback's signature to match the expected type from props or an interface.

javascript
type OnSelect = (id: string) => void; const handleSelect: OnSelect = useCallback((id) => { console.log(id); }, []);

Or, to avoid writing extra code:

javascript
const handleSelect = useCallback<OnSelect>((id) => { console.log(id); }, []);

We specify the generic <OnSelect> right on useCallback. This forces TypeScript to strictly check the function's signature.


3. Fully typing the signature inside useCallback

If you want everything explicit in one place:

javascript
const handleChange = useCallback<(event: React.ChangeEvent<HTMLInputElement>) => void>( (event) => { console.log(event.target.value); }, [] );

Now handleChange is strictly typed as ChangeEventHandler<HTMLInputElement>.


4. An example with a return value

javascript
const compute = useCallback((a: number, b: number): number => { return a + b; }, []);

Type:

javascript
(a: number, b: number) => number

TypeScript infers the type automatically - there's no need to explicitly write useCallback<number>.


5. Typing alongside React.FC or props

Suppose we have a component that receives a callback in its props:

javascript
type Props = { onSave: (data: string) => void; }; function Form({ onSave }: Props) { const handleSubmit = useCallback(() => { onSave('data'); }, [onSave]); return <button onClick={handleSubmit}>Save</button>; }

Here handleSubmit will automatically infer the type (event: React.MouseEvent<HTMLButtonElement>) => void, if you pass it to onClick.


6. Using it with event handlers

React already provides types for events:

javascript
const handleChange = useCallback( (e: React.ChangeEvent<HTMLInputElement>) => { console.log(e.target.value); }, [] );

or with a generic approach:

javascript
const handleClick = useCallback<React.MouseEventHandler<HTMLButtonElement>>( (e) => { e.preventDefault(); }, [] );

React.MouseEventHandler<T> = (event: React.MouseEvent<T, MouseEvent>) => void


7. If you need to type a generic function

javascript
const identity = useCallback(<T,>(value: T): T => { return value; }, []);

Usage:

javascript
identity(123); // number identity('hello'); // string

The generic is preserved - useCallback works correctly with <T,>.


8. Using it together with useMemo

If useCallback returns a complex function, you can explicitly type its signature and pass it to memoization:

javascript
type FetchFn = (url: string) => Promise<Response>; const fetchData = useCallback<FetchFn>(async (url) => { const res = await fetch(url); return res; }, []);

9. Common mistakes

Mistake 1: not specifying dependencies

javascript
const handle = useCallback(() => console.log(value), []);

If value changes, the function will "hang on" to the old value. Fix it:

javascript
const handle = useCallback(() => console.log(value), [value]);

Mistake 2: wrong generic order

javascript
useCallback<void, [string]>((value) => {}, []); // this doesn't work

This syntax doesn't work. useCallback accepts one generic - the whole function type:

javascript
useCallback<(value: string) => void>((value) => {}, []);

Summary

ScenarioHow to type it
A simple functionAutomatically (TS infers it)
A defined signatureuseCallback<FnType>(...)
A callback from propsconst cb: Props["onChange"] = useCallback(...)
React eventsuseCallback<React.ChangeEventHandler<HTMLInputElement>>
A generic functionuseCallback<<T,>(x: T) => T>

Recommendations

  • Don't type it manually if TypeScript can infer the type.
  • If the type matters for compatibility with props, use a generic on useCallback<>().
  • For events, use the built-in types from React.*EventHandler.
  • For generic functions, don't forget the comma <T,>.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.