Typed API client
Request
Cedar Scheduling needs a typed person client against a local mocked endpoint.
Data
Parallel payload and status arrays are the mocked responses in request order. A retry consumes the next entry. Only 503 is retryable.
Deliverable
A strictly checked client that validates JSON, person shape and requested id, uses at most the configured retry budget, and returns a discriminated success or error outcome.
Cedar Scheduling, a fictional appointment planner, needs a client for a local mocked person endpoint. You will build it in seven continuing steps. Start with the raw transport response, then add HTTP handling, JSON parsing, shape validation, request identity, and a bounded retry policy. The final result is a discriminated outcome that callers can inspect without guessing what a string means. All responses are supplied in order; no network is involved. Each step begins with your previous implementation and changes the checked behavior. Keep the earlier protections as you add the next one. A successful status does not prove a valid JSON body or a matching person record.
type ApiPerson = { id: string; name: string };
type MockResponse = { status: number; body: string };
async function mockGet(payloads: string[], statuses: number[], index: number): Promise<MockResponse> { return { status: statuses[index] ?? 404, body: payloads[index] ?? "" }; }
function isApiPerson(value: unknown): value is ApiPerson { return typeof value === "object" && value !== null && "id" in value && typeof value.id === "string" && "name" in value && typeof value.name === "string"; }
async function solve(id: string, payloads: string[], statuses: number[], retries: number): Promise<string[]> { const response = await mockGet(payloads, statuses, 0); return [String(response.status), response.body]; }
For status 503 followed by status 200, one allowed retry reaches the second mocked response. The final success tuple is ["ok:p1", "Mira"].