TypeDrop
2026-03-24 Challenge
2026-03-24
Medium
Typed Paginated API Response Aggregator
You're building the data-sync layer for a dashboard that pulls records from a paginated REST API. The fetcher must handle typed pages, collect results across all pages with a concurrency limit, and surface either a fully aggregated dataset or a structured `Result<T, E>` error — with zero `any`.
Goals
- Implement the `ok` and `err` Result constructors and use them throughout without type assertions.
- Fetch page 1 first to discover `totalPages`, then fetch remaining pages in concurrency-limited batches.
- Respect the `failFast` flag — abort with `Err<AggregateError>` on the first failure, or accumulate errors into `failedPages` when lenient.
- Implement `formatFetchError` with an exhaustive discriminated-union switch so TypeScript catches any missing case.
challenge.ts
// Core types at a glance
type ApiRecord<T> = { id: string; createdAt: string; payload: T };
type Page<T> = { page: number; totalPages: number; items: ApiRecord<T>[] };
type FetchError =
| { kind: "network"; message: string; page: number }
| { kind: "timeout"; page: number; afterMs: number }
| { kind: "parse"; page: number; raw: string }
| { kind: "unknown"; page: number; cause: unknown };
type PageFetcher<T> = (page: number) => Promise<Result<Page<T>, FetchError>>;
// Main function to implement:
async function aggregatePages<T>(
fetchPage: PageFetcher<T>,
config: { concurrency: number; failFast: boolean }
): Promise<Result<AggregateSuccess<T>, AggregateError>> { ... }
Hints (click to reveal)
Hints
- Batch an array of page numbers into chunks of size `concurrency` and `await Promise.all(chunk.map(...))` each batch sequentially.
- The `Result<T, E>` discriminant is `ok: true/false` — narrow it with an `if (result.ok)` check, never with `as`.
- For exhaustive matching in `formatFetchError`, add a `default` branch that assigns to a `never` variable to get a compile-time safety net.
Useful resources
Or clone locally
git clone -b challenge/2026-03-24 https://github.com/niltonheck/typedrop.git