Back to Snippets
TypeScriptTypeScript

TypeScript Generic API Client

A type-safe, reusable HTTP client with generics and interceptors.

typescriptapifetchgeneric
interface ApiResponse<T> {
  data: T
  status: number
}

class ApiClient {
  constructor(private baseUrl: string, private headers: Record<string, string> = {}) {}

  private async request<T>(endpoint: string, options?: RequestInit): Promise<ApiResponse<T>> {
    const res = await fetch(class="text-emerald-400">`${this.baseUrl}${endpoint}`, {
      ...options,
      headers: { class=class="text-emerald-400">"text-emerald-400">'Content-Type': class=class="text-emerald-400">"text-emerald-400">'application/json', ...this.headers, ...options?.headers },
    })
    if (!res.ok) throw new Error(class="text-emerald-400">`HTTP ${res.status}: ${res.statusText}`)
    const data = await res.json()
    return { data, status: res.status }
  }

  get<T>(endpoint: string) {
    return this.request<T>(endpoint)
  }

  post<T>(endpoint: string, body: unknown) {
    return this.request<T>(endpoint, { method: class=class="text-emerald-400">"text-emerald-400">'POST', body: JSON.stringify(body) })
  }

  put<T>(endpoint: string, body: unknown) {
    return this.request<T>(endpoint, { method: class=class="text-emerald-400">"text-emerald-400">'PUT', body: JSON.stringify(body) })
  }

  delete<T>(endpoint: string) {
    return this.request<T>(endpoint, { method: class=class="text-emerald-400">"text-emerald-400">'DELETE' })
  }
}

export const api = new ApiClient(class=class="text-emerald-400">"text-emerald-400">'/api', { Authorization: class=class="text-emerald-400">"text-emerald-400">'Bearer token' })

How to Use

Create an instance and call typed methods: const { data } = await api.get<User[]>('/users'). TypeScript infers the response type automatically. Set default headers like auth tokens in the constructor.

Related Technology

TypeScript

Have a Project in Mind?

Let's discuss how we can bring your idea to life. From initial concept to production-ready product — we've got you covered.

or book a free call