TypeDrop
2026-02-26 Challenge
2026-02-26
Easy
Typed Product Inventory Aggregator
You're building a back-office tool for an e-commerce warehouse. Raw inventory records arrive as unknown JSON, and you must safely validate them, group them by category, and compute per-category summaries — the challenge is keeping every step fully typed without reaching for `any`.
Goals
- Implement `parseProduct` to safely narrow `unknown` → `Product` using a `Result` discriminated union — no `any` or `as` allowed.
- Implement `groupByCategory` to bucket valid products into a `Map<Category, Product[]>`.
- Implement `summariseCategory` to compute per-category totals, averages (2 d.p.), and the cheapest product using `Pick<Product, ...>`.
- Implement `buildInventoryReport` to orchestrate the full pipeline: parse all raw records, collect indexed `ParseError`s, aggregate summaries, and return a sorted `InventoryReport`.
challenge.ts
// Key types
export type Category = "electronics" | "clothing" | "food" | "furniture";
export interface Product {
id: string;
name: string;
category: Category;
priceUsd: number; // > 0
stock: number; // non-negative integer
}
export type Result<T, E> =
| { ok: true; value: T }
| { ok: false; error: E };
export interface CategorySummary {
category: Category;
productCount: number;
totalStock: number;
averagePriceUsd: number;
cheapestProduct: Pick<Product, "id" | "name" | "priceUsd">;
}
// Functions to implement
export function parseProduct(raw: unknown): Result<Product, string> { ... }
export function groupByCategory(products: Product[]): Map<Category, Product[]> { ... }
export function summariseCategory(category: Category, products: Product[]): CategorySummary { ... }
export function buildInventoryReport(rawRecords: unknown[]): InventoryReport { ... }
Hints (click to reveal)
Hints
- Narrow `unknown` incrementally: first check `typeof raw === 'object' && raw !== null`, then use the `in` operator to confirm each field exists before checking its type or value.
- The `Result<T, E>` union is discriminated on the `ok` boolean — TypeScript will narrow `value` vs `error` automatically inside an `if (result.ok)` block.
- For `Pick<Product, 'id' | 'name' | 'priceUsd'>`, you don't need to construct a new type — just return an object literal with exactly those three keys and TypeScript will enforce the shape.
Useful resources
Or clone locally
git clone -b challenge/2026-02-26 https://github.com/niltonheck/typedrop.git