Challenge 3: Add a Third Required Field to the Builder — Possible Solution ==================================================================== type RequestBuilderState = { url?: string; method?: string; headers?: Record; }; class RequestBuilder { private state: State; constructor(state: State) { this.state = state; } url(value: string): RequestBuilder { return new RequestBuilder({ ...this.state, url: value }); } method(value: string): RequestBuilder { return new RequestBuilder({ ...this.state, method: value }); } headers(value: Record): RequestBuilder }> { return new RequestBuilder({ ...this.state, headers: value }); } build( this: RequestBuilder> ): { url: string; method: string; headers: Record } { return this.state as { url: string; method: string; headers: Record }; } } // --- Usage --- const request = new RequestBuilder({}) .url("/users") .method("POST") .headers({ "Content-Type": "application/json" }) .build(); // ✅ all three required fields were set console.log(request); // { url: "/users", method: "POST", headers: { "Content-Type": "application/json" } } // Each of these fails to compile — .build() itself is not a callable // member on a RequestBuilder missing any one required field: // new RequestBuilder({}).url("/users").method("POST").build(); // ❌ Property 'build' does not exist on type // 'RequestBuilder<{ url: string; method: string }>' in a way that // satisfies `this: RequestBuilder>` — // `headers` was never set. // new RequestBuilder({}).url("/users").headers({}).build(); // ❌ missing `method` // new RequestBuilder({}).method("POST").headers({}).build(); // ❌ missing `url` WHY THIS WORKS -------------- - Adding `headers` followed the exact same pattern as `url` and `method`: a setter method that returns `RequestBuilder`, accumulating one more required key onto the tracked State type. - `Required` expands to `{ url: string; method: string; headers: Record }` — all three properties now non-optional — so `build()`'s `this` parameter type demands all three have been set, not just the original two. - Because `this` parameter types are structurally checked, calling `.build()` on any RequestBuilder instantiation whose State is missing even one of the three required keys fails to satisfy that `this` constraint, and TypeScript reports `.build` as not callable there — the compile-time equivalent of a runtime "missing required field" error, just impossible to ship in the first place.