~/swaraj.dev
Back to all posts
March 20, 20261 min read

Typed API Hooks with React Query and TypeScript Generics

Leverage TypeScript generics to build reusable, type‑safe data‑fetching hooks with React Query, reducing boilerplate and catching API contract errors at compile time.

typescriptreact-queryreact-nativeapi

Insight

Creating a separate hook for every endpoint quickly becomes noisy, especially when the response shape varies. By defining a single generic useApi hook you let TypeScript infer the payload type from the function you pass in, while React Query still handles caching, retries, and background refetching. This pattern keeps your component code clean and guarantees that you only ever access fields that exist on the response.

Example

import { useQuery, UseQueryOptions } from '@tanstack/react-query';
import { fetch } from 'expo-network';

// Generic hook
function useApi<T>(
  key: string[],
  url: string,
  options?: UseQueryOptions<T>
) {
  return useQuery<T>(key, async () => {
    const res = await fetch(url);
    return (await res.json()) as T;
  }, options);
}

// Usage in a component
type User = { id: string; name: string; email: string };
const { data, isLoading } = useApi<User>(['user', id], `/api/users/${id}`);

Takeaway

Wrap your fetch logic in a single generic hook and let TypeScript do the heavy lifting. You’ll get autocomplete for response fields, fewer duplicate hooks, and a consistent caching strategy across your app.