TypeDrop

2026-07-15 Challenge

2026-07-15 Easy

Typed CSV Row Parser & Aggregator

You're building the data-import feature for a budgeting app. Raw CSV rows arrive as plain strings; your module must parse and validate each row into a strongly-typed `Transaction` record, collect typed parse errors, and then aggregate the valid rows into a per-category `SpendingSummary` — with zero `any`.

Goals

  • Define `ParseResult<T>` as a generic discriminated union with `ok: true` and `ok: false` variants.
  • Implement `parseTransactionRow` that validates all five rules and returns the correct `ParseResult<Transaction>` variant.
  • Implement `parseAll` that separates valid transactions from structured error entries in a single pass.
  • Define `SpendingSummary` as a mapped type over `Category` and implement `summariseByCategory` so every category key is always present in the output.
challenge.ts
// Key types you must define and implement:

export type Category = "food" | "transport" | "utilities" | "entertainment" | "other";

export interface Transaction {
  date: string;        // YYYY-MM-DD
  amount: number;      // positive, ≤ 2 decimal places
  category: Category;
  description: string; // non-empty
}

// Discriminated union — you define this:
export type ParseResult<T> = /* TODO */ never;

// Mapped type over Category — you define this:
export type SpendingSummary = /* TODO */ never;

// Functions you must implement:
export function parseTransactionRow(row: string): ParseResult<Transaction>;
export function parseAll(rows: string[]): ParseAllResult;
export function summariseByCategory(transactions: Transaction[]): SpendingSummary;
Hints (click to reveal)

Hints

  • For `ParseResult<T>`, a discriminated union uses a shared literal field (like `ok`) as the discriminant — TypeScript can then narrow the type in an `if` block.
  • For `SpendingSummary`, `{ [K in Category]: { total: number; count: number } }` ensures every category key is always present — seed them all to zero before iterating.
  • To validate `category`, build a `Set` or `const` array of all valid `Category` values and write a type-guard function that returns `value is Category`.

Or clone locally

git clone -b challenge/2026-07-15 https://github.com/niltonheck/typedrop.git