Suggest an editImprove this articleRefine the answer for “How do you type useMemo()?”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)The type for **`useMemo()`** can almost always be **left out** - TypeScript infers it on its own. **Key point:** if you return `null`, a complex structure, or a `Map`, use the generic: `useMemo<Type>()`.Shown above the full answer for quick recall.Answer (EN)Image```javascript // Without a type - TS will infer (User | null) const user = useMemo<User | null>(() => { if (!isLoggedIn) return null; return { id: 1, name: "Alex" }; }, [isLoggedIn]); ``` We use the generic: ```javascript useMemo<Type>(() => value, deps); ``` --- ## 4. An example with arrays ```javascript const filtered = useMemo(() => data.filter(x => x.active), [data]); // TS will infer the type as (typeof data)[] ``` If you need to be more specific: ```javascript const filtered = useMemo<ItemType[]>(() => data.filter(...), [data]); ``` --- ## 5. An example with objects and union types ```javascript type State = { status: "ok"; data: number[] } | { status: "error"; error: string }; const state = useMemo<State>(() => { try { return { status: "ok", data: [1, 2, 3] }; } catch { return { status: "error", error: "Oops" }; } }, []); ``` Now `state.status` is checked through a `switch` with no errors. --- ## 6. useMemo + functions If you are caching a **function**, you can type its signature: ```javascript const getById = useMemo<((id: number) => Item | undefined)>(() => { return (id) => items.find(x => x.id === id); }, [items]); const item = getById(5); ``` > An alternative is `useCallback`, if you are specifically caching a callback. --- ## 7. An example with `Map`, `Set`, and complex structures ```javascript const map = useMemo<Map<string, number>>(() => new Map(), []); map.set("a", 1); ``` > Without an explicit type, TS sometimes infers `Map<any, any>`. --- ## 8. If `useMemo` returns `null` in some branches ```javascript const element = useMemo<JSX.Element | null>(() => { if (!visible) return null; return <Chart data={data} />; }, [visible, data]); ``` Now TS knows that `element` can be `null`. --- ## 9. Combined examples ```javascript const config = useMemo<{ url: string; method: "GET" | "POST" }>( () => ({ url: `/api/${id}`, method: "GET" }), [id] ); const complex = useMemo< { title: string; tags: string[] } | null >(() => (ready ? { title: "Hello", tags } : null), [ready, tags]); ``` --- ## 10. General tips | Scenario | Typing | |---|---| | Simple values | Do not specify it - TS infers it on its own | | Arrays, objects | You can explicitly write `useMemo<T[]>(...)` or `useMemo<Record<string, T>>()` | | Union types (`null`, `undefined`) | Specify `<T | | `Map`, `Set`, `Date` | Specify `<Map<K, V>>`, `<Set<T>>`, `<Date>` | | Functions | Either `useCallback`, or `useMemo<FnType>(...)` | --- ## 11. The internal type of `useMemo` ```javascript function useMemo<T>(factory: () => T, deps: DependencyList): T; ``` That is, `useMemo` accepts **a function that returns T**, and returns `T`. --- ## Summary | What to type | How | |---|---| | Numbers, strings, booleans | `useMemo(() => ..., [...])` - automatic | | Objects / arrays | `useMemo<T>(() => ..., [...])` | | Nullable / optional | `useMemo<T | | Map / Set | `useMemo<Map<K, V>>(() => ..., [...])` | | Functions | `useMemo<FnType>(() => ..., [...])` | --- > **The main point:** > > - You can almost always **leave the type out** - TS infers it itself. > - But if you return `null`, a complex structure, or a `Map`, > use the generic: `useMemo<Type>()`. > - Do not confuse `useMemo` (a value) with `useCallback` (a function). </content>For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.