TypeDrop

2026-05-09 Challenge

2026-05-09 Hard

Typed Streaming ETL Pipeline

You're building the data-ingestion layer for a real-time analytics platform. Raw event batches arrive as `unknown` from multiple upstream sources; your pipeline must validate them, transform each event through a typed middleware chain, fan-out to per-topic async sinks with a concurrency limit, and return a strongly-typed pipeline execution report — with zero `any`.

Goals

  • Implement `makeEventId`, `makeTopicName`, and `makeSourceId` using a `Result`-returning branded-type constructor — no `as` or `any` allowed.
  • Define `MiddlewareChain<MS>` as a recursive conditional type that resolves to the final output payload type when every adjacent middleware pair is compatible, and `never` otherwise.
  • Implement `validateEvent`, `runMiddlewares`, and `fanOutToSinks` so that validation, sequential middleware execution with short-circuit, and concurrency-limited sink fan-out all work correctly.
  • Wire everything together in `runPipeline` to produce a fully accurate `PipelineReport` with correct counts and per-topic breakdown.
challenge.ts
// Key types and main entry point — challenge.ts (preview)

type Brand<T, B extends string> = T & { readonly __brand: B };
export type EventId   = Brand<string, "EventId">;
export type TopicName = Brand<string, "TopicName">;

export type Result<T, E> =
  | { readonly ok: true;  readonly value: T }
  | { readonly ok: false; readonly error: E };

export type Middleware<
  TIn  extends Record<string, unknown>,
  TOut extends Record<string, unknown>
> = (event: TransformedEvent<TIn>) => Promise<Result<TransformedEvent<TOut>, PipelineError>>;

// Your job: make this recursive conditional type validate chain compatibility
export type MiddlewareChain<
  MS extends readonly Middleware<Record<string, unknown>, Record<string, unknown>>[]
> = /* TODO */ unknown;

export async function runPipeline<Topics extends TopicName>(
  rawBatch: ReadonlyArray<unknown>,
  config: PipelineConfig<Topics>
): Promise<PipelineReport> {
  // TODO — validate → transform → fan-out → report
  throw new Error("not implemented");
}
Hints (click to reveal)

Hints

  • For `MiddlewareChain`, write a helper type `InferMiddlewareOut<M>` using `infer` to extract the `TOut` type from a single `Middleware<TIn, TOut>`, then recurse over the tuple checking that `InferMiddlewareOut<MS[N]>` extends the `TIn` of `MS[N+1]`.
  • To enforce the concurrency limit in `fanOutToSinks` without a library, maintain an in-flight counter and a queue of pending tasks — resolve the next queued task each time an in-flight one completes.
  • Branded types can be constructed safely by returning `ok(raw as EventId)` only inside the dedicated `makeEventId` function — this is the one place where a cast is acceptable because the function itself IS the runtime guard.

Or clone locally

git clone -b challenge/2026-05-09 https://github.com/niltonheck/typedrop.git