Challenge 2: Extend ExtractParams for Wildcards — Possible Solution ==================================================================== type ExtractParams = Path extends `${string}:${infer Param}/${infer Rest}` ? { [K in Param | keyof ExtractParams]: string } : Path extends `${string}:${infer Param}` ? { [K in Param]: string } : Path extends `${string}*` ? { wildcard: string } : {}; // --- Usage --- type A = ExtractParams<"/files/*">; // { wildcard: string } type B = ExtractParams<"/users/:userId/posts/:postId">; // { userId: string; postId: string } — unchanged from the chapter's version type C = ExtractParams<"/users/:userId/*">; // { userId: string; wildcard: string } — combines a named param AND a // trailing wildcard in the same path function buildUrl( path: Path, params: ExtractParams ): string { let url: string = path; for (const [key, value] of Object.entries(params)) { if (key === "wildcard") { url = url.replace("*", value as string); } else { url = url.replace(`:${key}`, value as string); } } return url; } buildUrl("/files/*", { wildcard: "report.pdf" }); // "/files/report.pdf" buildUrl("/users/:userId/*", { userId: "42", wildcard: "profile.jpg" }); // "/users/42/profile.jpg" WHY THIS WORKS -------------- - The new third branch, `Path extends \`${string}*\`` , only gets checked after both colon-based patterns fail to match — so a path with no `:` segments at all (like "/files/*") falls through to it, while a path that DOES have a `:param` is still handled by the earlier branches first. - Because the first branch's `infer Rest` recurses via `ExtractParams`, a path combining both a named param and a trailing wildcard (like "/users/:userId/*") naturally merges both: the first branch extracts "userId" and recurses on "*", and that recursive call is what hits the new wildcard branch and contributes "wildcard" to the final key union. - No changes were needed to the recursive merging logic itself (`{ [K in Param | keyof ExtractParams]: string }`) — adding a new terminal case is purely additive, which is a good sign the original recursive structure was designed sensibly.