TypeScript Generic API Client
Type-safe fetch wrapper with generics, error handling, and abort support.
type ApiResponse<T> = { data: T; error: null } | { data: null; error: string };
async function apiClient<T>(
url: string,
options?: RequestInit & { signal?: AbortSignal }
): Promise<ApiResponse<T>> {
try {
const res = await fetch(url, {
headers: { 'Content-Type': 'application/json' },
...options,
});
if (!res.ok) {
const msg = await res.text();
return { data: null, error: msg || res.statusText };
}
const data: T = await res.json();
return { data, error: null };
} catch (err) {
return { data: null, error: (err as Error).message };
}
}
// Usage
interface User { id: number; name: string }
const { data, error } = await apiClient<User[]>('/api/users');
if (error) console.error(error);
else console.log(data);