Challenge 2: Type a Query Builder Result — Possible Solution ==================================================================== interface Database { products: { id: number; name: string; price: number; category: string; }; } // A minimal typed "select columns" helper — the same idea a real query // builder like Kysely applies at much larger scale. function selectColumns< TTable extends keyof Database, TColumns extends keyof Database[TTable] >( _table: TTable, columns: TColumns[] ): Pick { // (Real implementation would run SQL; this signature is the point of the // exercise — the return type is DERIVED, not hand-written.) return {} as Pick; } // --- Usage --- const result = selectColumns("products", ["name", "price"]); // result is inferred as { name: string; price: number } — // NOT the full products row, and NOT `any`. console.log(result.name); // ✅ compiles — string console.log(result.price); // ✅ compiles — number // console.log(result.category); // ❌ compile error: "category" was never selected // A typo in the table or column name is also caught immediately: // selectColumns("prodcuts", ["name"]); // ❌ "prodcuts" is not keyof Database // selectColumns("products", ["nmae"]); // ❌ "nmae" is not keyof Database["products"] WHY THIS WORKS -------------- - `TTable extends keyof Database` restricts the first argument to an actual table name defined on Database — a typo fails at compile time instead of silently querying nothing. - `TColumns extends keyof Database[TTable]` does the same for column names, scoped to whichever table was selected. - `Pick` builds the return type by picking only the requested columns off the full row type — exactly mirroring how a real query builder narrows the result shape to what was actually selected, the same idea Kysely and Prisma's `select` option use under the hood.