TypeDrop
2026-04-17 Challenge
2026-04-17
Hard
Typed Query Plan Builder
You're building the query planning layer for an in-memory analytics engine. Raw query descriptors arrive as unknown JSON from a REST API; your planner must validate them, compile them into a strongly-typed execution plan through a composable operator pipeline, execute each operator with typed intermediate results, and surface a discriminated-union outcome per stage — with zero `any`.
Goals
- Define `OperatorExecutor<O>` as a generic function type constrained to `PlanOperator` variants, and `ExecutorRegistry` as a mapped type using `Extract` to pair each `OperatorKind` key with its correctly-typed executor.
- Implement `validateQuery` to safely narrow `unknown` input into a `ValidatedQuery`, branding all field and table name strings, and returning typed `QueryError` discriminants on every violation.
- Implement `buildPlan` to compile a `ValidatedQuery` into an ordered `ExecutionPlan`, enforcing the groupBy-select compatibility rule and emitting only the operators that apply.
- Implement `executePlan` to fold over the plan's operator array, dispatch each operator through the `ExecutorRegistry`, collect per-stage metrics, and short-circuit on the first execution error.
challenge.ts
// Key types and main orchestrator signature
type OperatorExecutor<O extends PlanOperator> =
(operator: O, rows: ReadonlyArray<Row>, registry: TableRegistry)
=> Result<ReadonlyArray<Row>, QueryError>;
type ExecutorRegistry = {
[K in OperatorKind]: OperatorExecutor<Extract<PlanOperator, { kind: K }>>;
};
// Discriminated operator union (one variant shown):
interface FilterOperatorNode { readonly kind: "filter"; readonly clause: FilterClause; }
interface ScanOperator { readonly kind: "scan"; readonly table: TableName; }
// … + project | groupBy | sort | limit
// Top-level orchestrator — compose all four stages:
function runQuery(
raw: unknown,
registry: TableRegistry
): Result<QueryReport, QueryError>;
Hints (click to reveal)
Hints
- For `ExecutorRegistry`, the mapped type key `K` extends `OperatorKind` — use `Extract<PlanOperator, { kind: K }>` as the type argument to `OperatorExecutor<…>` so each executor is narrowed to its exact operator variant.
- Inside `executePlan`, a `switch (operator.kind)` over the discriminant lets TypeScript narrow `operator` to the specific variant, allowing you to index `executors[operator.kind]` with the correctly-typed argument without any cast.
- Brand `FieldName` and `TableName` by writing a runtime-validated helper (e.g. `toFieldName(s: string): FieldName`) that asserts the non-empty invariant before returning `s as FieldName` — keep the cast inside the helper so the rest of the code stays assertion-free.
Useful resources
Or clone locally
git clone -b challenge/2026-04-17 https://github.com/niltonheck/typedrop.git