TypeDrop
2026-04-15 Challenge
2026-04-15
Easy
Typed CSV Report Parser
You're building the data-import pipeline for a sales analytics dashboard. Raw CSV text arrives from uploaded files as plain strings; your parser must validate each row, transform it into a strongly-typed record, and return a typed parse report — with zero `any`.
Goals
- Define the `RowResult` discriminated union and complete the `ParseReport` interface, including using `Extract<>` for the `failures` field.
- Implement the generic `ColumnSchema<T>` interface and fill in all six `SALE_COLUMNS` entries with correct parse and validate logic, using `satisfies`.
- Implement `parseRow` to validate cell counts, catch parse errors, collect validation errors, and return the correct `RowResult` variant.
- Implement `parseCSV` (header validation, blank-line skipping, report assembly) and `revenueByRegion` (per-region sum via `Record<Region, number>`, zero-initialised, rounded to 2 dp).
challenge.ts
// Core domain types + main function signature
export type Region = "NA" | "EU" | "APAC" | "LATAM";
export interface SaleRecord {
id: string;
region: Region;
product: string;
quantity: number;
unitPrice: number;
saleDate: Date;
}
// Generic column descriptor — T defaults to string
export interface ColumnSchema<T = string> {
header: string;
parse: (raw: string) => T; // may throw on bad input
validate: (value: T) => string | null; // null = valid
}
// Discriminated union for per-row parse outcome
export type RowResult =
| { ok: true; value: SaleRecord }
| { ok: false; rowIndex: number; raw: string; errors: string[] };
// Main entry point
export function parseCSV(csv: string): ParseReport { /* TODO */ }
Hints (click to reveal)
Hints
- The `failures` field type in `ParseReport` should use `Extract<RowResult, { ok: false }>[]` — let TypeScript derive the narrowed type rather than duplicating it.
- For `SALE_COLUMNS`, each entry has its own concrete `T`; annotate the array with `satisfies ReadonlyArray<ColumnSchema<unknown>>` so TypeScript checks each entry without widening individual `parse` return types.
- Inside `parseRow`, iterate over `schemas` with an index; wrap each `schema.parse(cells[i])` in a try/catch and only call `schema.validate` if parsing succeeded — then decide `ok: true` or `ok: false` at the end.
Useful resources
Or clone locally
git clone -b challenge/2026-04-15 https://github.com/niltonheck/typedrop.git