Write a type-safe API client from a route map: each route takes the right body and resolves to the right response type.
createClient<Routes>(send) returns a client whose request(route, body) only accepts the routes in Routes, requires a body exactly when the route has one, and resolves to that route's response type. send makes the real HTTP call; you only add the types.
type RouteMap = Record<string, { body: unknown; response: unknown }>;type Send = (route: string, body: unknown) => Promise<unknown>; function createClient(send: Send) { return { request(route: string, body?: unknown): Promise<unknown> { return send(route, body); }, };} // type Routes = {// "GET /users": { body: undefined; response: User[] };// "POST /users": { body: { name: string }; response: User };// };// const api = createClient<Routes>(send);// api.request("GET /users"); // Promise<User[]>// api.request("POST /users", { name: "Ada" }); // Promise<User>// api.request("POST /users"); // error: the body is missing// api.request("GET /posts"); // error: no such routeThe answer
Write it yourself first. Then compare it with a reference solution and the checks it passes.
Checking your sign-in…