TypeDrop
2026-05-03 Challenge
2026-05-03
Medium
Typed In-Memory Search Index
You're building the client-side search layer for a documentation site. Raw document payloads arrive as `unknown` from a local JSON bundle; your engine must validate them, build an inverted index over configurable fields, and return strongly-typed ranked results — with zero `any`.
Goals
- Implement `ExtractFields<C>` and `WeightMap<F>` using `infer` and built-in utility types.
- Implement `validateDocument` to narrow `unknown` → `IndexedDocument` and return a discriminated-union `ValidationResult` — no `any` or `as`.
- Implement `tokenise` to lower-case, split, and filter a string into clean tokens.
- Implement the full `SearchIndex<F>` class: build a weighted inverted index on `add`, and return ranked `SearchResult` discriminated-union hits on `search`.
challenge.ts
// Key types & main class signature
interface IndexConfig<F extends string> {
fields: readonly F[];
fieldWeights?: Partial<Record<F, number>>;
}
interface SearchHit {
id: string;
score: number;
fields: Record<string, string>;
}
type SearchResult =
| { kind: "results"; hits: SearchHit[]; query: string }
| { kind: "empty"; query: string };
type ValidationResult =
| { kind: "ok"; document: IndexedDocument }
| { kind: "error"; reason: string; raw: unknown };
// ── Your main entry point ────────────────────────────────────
class SearchIndex<F extends string> {
constructor(config: IndexConfig<F>) { /* TODO */ }
add(raw: unknown): ValidationResult { /* TODO */ }
search(query: string): SearchResult { /* TODO */ }
size(): number { /* TODO */ }
}
Hints (click to reveal)
Hints
- For `validateDocument`, use `typeof` and `in` operator checks to narrow `unknown` step by step — TypeScript will track the type for you without needing `as`.
- In the `SearchIndex` constructor, build the `WeightMap<F>` by spreading a default-weight object over `config.fieldWeights` — `Object.fromEntries` paired with `config.fields.map` keeps it type-safe.
- The inverted index maps `token → Map<docId, weightedCount>` — when indexing, multiply the raw term-frequency by the field's weight before storing.
Useful resources
Or clone locally
git clone -b challenge/2026-05-03 https://github.com/niltonheck/typedrop.git