typespec1-4 Exercise 2: Where Do the Parameters Go? ========================================================== search_bad.tsp: import "@typespec/http"; using Http; @service(#{ title: "Search Service" }) namespace SearchService; model Result { id: string; title: string; } @route("/search") interface Search { @get find(term: string, limit?: int32): Result[]; @route("{id}") @get fetch(id: string): Result; } PREDICTION find(term, limit?) has no decorators and is a GET, so TypeSpec will put term and limit in a request BODY. (That is the mistake.) fetch(id) has no @path, but the route is {id} and the parameter is called id, so it should be bound to the path anyway. Compiled and tabulated: operation inputs responses GET /search BODY 200 GET /search/{id} path:id 200 search_good.tsp differs in two lines: @get find(@query term: string, @query limit?: int32): Result[]; @route("{id}") @get fetch(@path id: string): Result; Compiled and tabulated: operation inputs responses GET /search query:term, query:limit 200 GET /search/{id} path:id 200 WHAT HAPPENED Prediction confirmed on both counts. The find operation in the first version is a GET with a request BODY (and the compiler said nothing). In the corrected version term and limit are query parameters. fetch was already right: the parameter named in the route's braces is a path parameter even without the decorator. Adding @path changes nothing in the output; it only states the intention. WHY THIS WORKS AS AN ANSWER --------------------------- The operations table makes the inference visible: BODY appearing in a GET row is the symptom to look for. Neither the compiler nor the linter would have found it. The habit is to decorate every parameter and to read this table after every change to an operation.