Skip to content

TypeScript Hooks

Custom hooks return typed values consumed by components. Generics enable reusable hooks like useLocalStorage<T> and useFetch<T>. This lesson covers hook typing patterns.

Typing Custom Hooks

Explicit return types on custom hooks document the API: function useToggle(): [boolean, () => void]. TypeScript infers most cases, but explicit returns help when logic is complex.

Generic hooks <T> preserve item types through fetch and storage utilities.

function useLocalStorage<T>(key: string, initial: T) {
  const [value, setValue] = useState<T>(() => {
    const stored = localStorage.getItem(key);
    return stored ? (JSON.parse(stored) as T) : initial;
  });
  useEffect(() => {
    localStorage.setItem(key, JSON.stringify(value));
  }, [key, value]);
  return [value, setValue] as const;
}

as const tuple return types enable destructuring with precise types.

Hook Typing Patterns

useRef<HTMLDivElement>(null)
useCallback((e: React.MouseEvent) => {}, [])
useContext<ThemeContextValue>(ThemeContext)
  • DOM refs: nullable element type on useRef.
  • Event handlers: specific React event generic.
  • Custom hooks exporting objects: define return interface.
  • Generic constraints: <T extends string> when needed.

Hook Event Types

Common React event types in TypeScript.

Event Type
Input change ChangeEvent<HTMLInputElement>
Form submit FormEvent<HTMLFormElement>
Button click MouseEvent<HTMLButtonElement>
Keyboard KeyboardEvent<HTMLElement>
Ref callback (node: HTMLDivElement | null) => void

Generic Data Hook

Type fetch hooks with generic default and error types for reusable data loading.

function useFetch<T>(url: string) {
  const [data, setData] = useState<T | null>(null);
  // ...
  return { data, loading, error };
}

ESLint + TypeScript for Hooks

Combine eslint-plugin-react-hooks with TypeScript-eslint for exhaustive deps and type-aware lint rules.

Common Mistakes

  • useRef without element type argument.
  • Wrong event type — using ChangeEvent on form submit.
  • Generic hook defaulting to any.
  • Not typing custom hook return when exporting from library.

Key Takeaways

  • Type custom hook returns explicitly for complex APIs.
  • Generics power reusable hooks like useLocalStorage<T>.
  • Use specific React event types for handlers.
  • Nullable refs require optional chaining on .current.

Pro Tip

Define type HookReturn = ReturnType<typeof useMyHook> for consumers needing the return shape.