TypeDrop

2026-09-03 Challenge

2026-09-03 Hard

Typed Schema-Validated ETL Pipeline with Branded Results

You're building the ingestion layer for a data-warehouse platform. Raw records arrive as `unknown` JSON blobs, must be validated against per-table schemas, transformed into strongly-typed domain rows, and either committed to a typed sink or collected into a structured error report — all without a single `any` or unsafe cast in sight.

Goals

  • Define a `FieldSchema` discriminated union and a `TableSchema` type that carries both field definitions and an optional required-field list.
  • Implement the `inferRow<S>` mapped + conditional type so required fields are non-optional, optional fields are optional, and `literal` fields carry their exact literal type.
  • Implement `validateRow` to safely narrow `unknown` → `Validated<inferRow<S>>` using runtime checks, returning a typed `Result` on both success and failure paths.
  • Implement `runPipeline` to process a batch of raw records through validation and transformation, write successes to the typed `Sink`, and return a fully populated `PipelineReport`.
challenge.ts
// Core types you must define and connect:

type FieldSchema =
  | { kind: "string" }
  | { kind: "number" }
  | { kind: "boolean" }
  | { kind: "literal"; value: string | number | boolean };

type TableSchema = {
  fields: Record<string, FieldSchema>;
  required?: readonly string[];
};

// Branded wrapper — only producible via validateRow
type Validated<T> = T & { readonly __validated: unique symbol };

// Mapped + conditional type (yours to implement)
type inferRow<S extends TableSchema> = /* ... */ never;

// Main pipeline entry-point
declare function runPipeline<S extends TableSchema, Out>(
  schema: S,
  transformer: Transformer<S, Out>,
  records: unknown[],
  sink: Sink<Out>
): PipelineReport;
Hints (click to reveal)

Hints

  • For `inferRow`, split the fields into two mapped types — one for required keys and one for optional — then intersect them. Use `S["required"][number]` to distribute required key names.
  • To infer the exact literal type from a `{ kind: "literal"; value: V }` field, write a helper conditional type `FieldToType<F extends FieldSchema>` that uses `infer V` on the `value` property.
  • The only safe place for a single `as` cast is the final `return ok(obj as Validated<inferRow<S>>)` inside `validateRow`, after every runtime check has already passed — keep all other code cast-free.

Or clone locally

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