TypeScript Types
Complete TypeScript API reference for typed-fetch
TypeScript Types
Complete reference for all TypeScript types exported by typed-fetch.
Main Export: typedFetch
export async function typedFetch<K extends TypedEndpointKey>(
input: RequestInfo | URL,
init?: RequestInit,
options: TypedFetchOptions<K>,
): Promise<TypedFetchResult<K>>;Alias: tFetch (shorter name for convenience)
Parameters
input
The URL to fetch. Can be a string, URL object, or Request:
await typedFetch("https://api.example.com/users/1", ...);
await typedFetch(new URL("/api/users/1", baseUrl), ...);init (optional)
Standard fetch RequestInit options:
await typedFetch(
url,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name: "John" }),
},
{ endpointKey },
);options
typed-fetch specific options:
interface TypedFetchOptions<K extends TypedEndpointKey> {
/** Required. Endpoint pattern, e.g. "GET /users/:id". */
endpointKey: K;
/** Optional config overrides. */
config?: Partial<TypedFetchConfig>;
/** Path to a typed-fetch config file. */
configPath?: string;
/** Optional cache for deduplication, stale-while-revalidate, and retry. */
cache?: TypedFetchCache;
}TypedEndpointKey
The type accepted by endpointKey. IDEs suggest all known keys while still allowing any string:
export type TypedEndpointKey = KnownEndpointKey | (string & {});
// ^-- auto-completed ^-- any string acceptedKnown keys come from TypedFetchGeneratedResponses (auto-generated) and TypedFetchUserEndpoints (manual declarations).
Return Type: TypedFetchResult
type TypedFetchResult<K extends TypedEndpointKey> =
| TypedFetchNetworkError<K>
| (K extends KnownEndpointKey
? KnownEndpointResult<K> // per-status typed via discriminated union
: { status: number; ok: boolean; data: unknown; response: Response });On success (any HTTP response including 4xx/5xx)
{
endpoint: K; // The endpointKey you provided
status: number; // HTTP status code (200, 404, 500, …)
ok: boolean; // true if status is 2xx (200–208, 226)
data: unknown; // Parsed JSON body (typed after generate)
response: Response; // Original Response object
error?: undefined;
}On network error (status === 0)
export type TypedFetchNetworkError<K extends TypedEndpointKey> = {
endpoint: K;
status: 0; // Always 0 — no HTTP response received
ok: false;
data: undefined;
response: null;
error: Error; // Network error details
};Discriminated Unions
The result type is designed for discriminated unions based on status:
const result = await typedFetch(url, init, { endpointKey: "GET /users/:id" });
if (result.status === 200) {
// result.data is typed for the 200 shape
console.log(result.data.name);
} else if (result.status === 404) {
console.log(result.data.error);
} else if (result.status === 0) {
// Network error
console.error(result.error.message);
}Generated Types: TypedFetchGeneratedResponses
After running npx typed-fetch generate, a .d.ts file augments this interface:
// src/generated/typed-fetch.d.ts (auto-generated — do not edit)
declare module "@phumudzo/typed-fetch" {
interface TypedFetchGeneratedResponses {
"GET /users/:id": {
200: { id: number; name: string; email: string };
404: null;
};
"POST /users": {
201: { id: number };
400: { message: string };
};
}
}Manual Types: TypedFetchUserEndpoints
Augment this interface to declare types for endpoints you haven't observed yet, or to override generated types. User-defined entries take priority over generated ones.
// src/typed-fetch.endpoints.d.ts
declare module "@phumudzo/typed-fetch" {
interface TypedFetchUserEndpoints {
"GET /users/:id": {
200: { id: number; name: string; email: string; role: "admin" | "user" };
404: { error: string };
};
// Third-party API without observation
"GET /repos/:owner/:repo": {
200: { id: number; name: string; stargazers_count: number };
404: { message: string };
};
}
}
export {};Caching: TypedFetchCache and CacheOptions
export type CacheOptions = {
staleTime?: number; // default: 0
gcTime?: number; // default: 300_000 (5 min)
retry?: number | false; // default: 3
retryDelay?: (attempt: number) => number; // default: exponential
};
export class TypedFetchCache {
buildKey(input: RequestInfo | URL, method: string): string;
get<T>(key: string): { result: T; fetchedAt: number; endpointKey: string } | undefined;
isStale(entry: { fetchedAt: number }): boolean;
set<T>(key: string, result: T, endpointKey: string): void;
getInFlight<T>(key: string): Promise<T> | undefined;
setInFlight<T>(key: string, promise: Promise<T>): void;
clearInFlight(key: string): void;
subscribe(key: string, cb: () => void): () => void;
invalidate(input: RequestInfo | URL, method?: string): void;
invalidateByEndpoint(endpointKey: string): void;
invalidateAll(): void;
destroy(): void;
}
export function createTypedFetchCache(options?: CacheOptions): TypedFetchCache;Client: createTypedFetchClient
const client = createTypedFetchClient({
baseUrl: "https://api.example.com",
config?: Partial<TypedFetchConfig>;
cache?: TypedFetchCache; // optional — applied to every request
});
const result = await client.fetch("/users/1", undefined, {
endpointKey: "GET /users/:id",
cache?, // per-call override
});Adapter Exports
typed-fetch provides additional adapter entry points for server frameworks:
import { observeResponse } from '@phumudzo/typed-fetch/adapters/generic';
import { typedFetchObserver } from '@phumudzo/typed-fetch/adapters/hono';
import { withTypedFetchObserver } from '@phumudzo/typed-fetch/adapters/next';observeResponse (generic)
export async function observeResponse(
endpointKey: string,
response: Response,
config?: Partial<TypedFetchConfig>,
): Promise<void>;- Observes JSON responses and queues shape observations.
- Schedules type generation after registry flush.
- Runs only in
NODE_ENV=development.
typedFetchObserver (Hono)
export function typedFetchObserver(
config?: Partial<TypedFetchConfig>,
): (c: HonoContext, next: () => Promise<void>) => Promise<void>;- Hono middleware that observes all route responses.
- Automatically builds endpoint keys from method +
routePath.
withTypedFetchObserver (Next.js)
export function withTypedFetchObserver(
endpointKey: string,
handler: (req: Request, ctx?: unknown) => Promise<Response>,
config?: Partial<TypedFetchConfig>,
): (req: Request, ctx?: unknown) => Promise<Response>;- Wraps Next.js App Router handlers.
- Requires explicit
endpointKey(file-system routes are not available at runtime).
Key Type Narrowing Patterns
Status-based narrowing
if (result.status === 200) {
// result.data is typed for 200
}Error checking
if (result.status === 0) {
console.error(result.error); // Error object
} else if (result.ok) {
console.log(result.data); // 2xx typed data
} else {
console.log(result.status); // 4xx / 5xx
}Function return type annotation
import type { TypedFetchResult } from "@phumudzo/typed-fetch";
async function getUser(id: number): Promise<TypedFetchResult<"GET /users/:id">> {
return typedFetch(`/api/users/${id}`, undefined, { endpointKey: "GET /users/:id" });
}Next: Result Object
Learn about the Result Object in detail.