Suggest an editImprove this articleRefine the answer for “How to type useCallback()?”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)`useCallback` returns a **memoized function** whose type depends on its body - TypeScript infers the type automatically if everything is declared explicitly. **Key point:** don't type it manually if TypeScript can infer the type itself; when the type matters for compatibility with props, use a generic on `useCallback<FnType>()`.Shown above the full answer for quick recall.Answer (EN)Image## 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. --- ## 1. The simplest option - automatic inference (recommended) 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 | Scenario | How to type it | |---|---| | A simple function | Automatically (TS infers it) | | A defined signature | `useCallback<FnType>(...)` | | A callback from props | `const cb: Props["onChange"] = useCallback(...)` | | React events | `useCallback<React.ChangeEventHandler<HTMLInputElement>>` | | A generic function | `useCallback<<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,>`.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.