TypeDrop
A new TypeScript challenge every day. Sharpen your types.
TypeDrop delivers a fresh TypeScript challenge every day, generated by AI. Pick a challenge, open it in StackBlitz (preferred) or CodeSandbox (or clone it locally), and make the tests pass. No accounts, no setup — just you and the type system.
2026-08-18
Medium
Typed Concurrent Task Scheduler with Priority Queues & Result Aggregation
You're building the background job runner for a data-pipeline platform. Tasks arrive with different priorities and async work functions; the scheduler must run at most N tasks concurrently, drain them in priority order, and return a strongly-typed aggregated report — successes, failures, and per-task durations — without ever widening to `unknown` unsafely or swallowing errors silently.
Goals
- Implement `makeConcurrency` to produce a branded `Concurrency` type, throwing `TypeError` for invalid inputs.
- Implement `sortByPriority` to return a stable-sorted copy of tasks using `PRIORITY_WEIGHT`, without mutating the input.
- Implement the `isSuccess` type predicate to correctly narrow `TaskResult<T>` to `TaskSuccess<T>`.
- Implement `runScheduler` to execute tasks concurrently up to the given limit, in priority order, capturing both successes and failures, and returning a fully-typed `SchedulerReport<T>` with correct `topResult` tie-breaking.
challenge.ts
// Key types & main function signature at a glance
type Priority = "critical" | "high" | "normal" | "low";
interface Task<T> {
readonly id: string;
readonly priority: Priority;
readonly run: () => Promise<T>;
}
type TaskSuccess<T> = { status: "fulfilled"; id: string; priority: Priority;
value: T; durationMs: number };
type TaskFailure = { status: "rejected"; id: string; priority: Priority;
reason: unknown; durationMs: number };
type TaskResult<T> = TaskSuccess<T> | TaskFailure;
type SchedulerReport<T> = {
readonly results: ReadonlyArray<TaskResult<T>>;
readonly totalDurationMs: number;
readonly successCount: number;
readonly failureCount: number;
readonly topResult: TaskSuccess<T> | null;
};
// Branded positive-integer concurrency limit
type Concurrency = Brand<number, "Concurrency">;
async function runScheduler<T>(
tasks: ReadonlyArray<Task<T>>,
concurrency: Concurrency
): Promise<SchedulerReport<T>>
Hints (click to reveal)
Hints
- For the concurrency pool in `runScheduler`, maintain a Set of in-flight Promises and use a recursive 'start-next' helper — each time a slot frees up, pull the next task from the sorted queue.
- To satisfy requirement 4h (original-index tie-breaking for `topResult`), tag each task with its original array index before sorting, then use that index when comparing successes of equal priority.
- A type predicate function has the return type `result is TaskSuccess<T>` — the compiler will use this to automatically narrow the union inside `if` blocks and `.filter()` calls.
Useful resources
Or clone locally
git clone -b challenge/2026-08-18 https://github.com/niltonheck/typedrop.git