<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:fh="http://purl.org/syndication/history/1.0"><channel><title>Tetsu | Blog</title><description/><link>https://tetsujs.com/</link><language>en</language><fh:complete/><atom:link rel="self" href="https://tetsujs.com/blog/rss.xml"/><item><title>Why write an HTTP framework in TypeScript in 2026?</title><link>https://tetsujs.com/blog/why-typescript-in-2026/</link><guid isPermaLink="true">https://tetsujs.com/blog/why-typescript-in-2026/</guid><description>Go and Rust are stricter than TypeScript, and agents now write much of our code. But someone still has to review it, and you review best in the language you already write. Why I wrote Tetsu in TypeScript, and what a framework can do to close part of the gap.</description><pubDate>Thu, 08 Oct 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In September, Jarred Sumner, who builds Bun,
&lt;a href=&quot;https://x.com/jarredsumner/status/2103092824363401586&quot;&gt;wrote&lt;/a&gt; that
“JavaScript was never designed for the server”, and that unless the engine
changes, Rust will replace it there. Many replies agreed and said to let
server-side JavaScript die. A week later Ryan Dahl, who created Node.js and
Deno and writes Rust as his main language,
&lt;a href=&quot;https://x.com/rough__sea/status/2106813105594593704&quot;&gt;answered&lt;/a&gt; that
application code belongs in JavaScript or TypeScript.&lt;/p&gt;
&lt;p&gt;I had just written Tetsu, an HTTP framework for Bun, in TypeScript, and I’d
been asking myself the same question while building it. Here’s my answer. It
starts with what Go and Rust do better, because they do a lot better.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;what-go-and-rust-do-better&quot;&gt;What Go and Rust do better&lt;/h2&gt;&lt;/div&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;TypeScript&lt;/th&gt;
&lt;th&gt;Go&lt;/th&gt;
&lt;th&gt;Rust&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Code with a type error&lt;/td&gt;
&lt;td&gt;runs: Bun and Node don’t check types&lt;/td&gt;
&lt;td&gt;doesn’t build&lt;/td&gt;
&lt;td&gt;doesn’t build&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A value matches its type&lt;/td&gt;
&lt;td&gt;not always: &lt;code dir=&quot;auto&quot;&gt;any&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;as&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;JSON.parse&lt;/code&gt; aren’t checked&lt;/td&gt;
&lt;td&gt;yes, except with &lt;code dir=&quot;auto&quot;&gt;unsafe&lt;/code&gt; or a data race&lt;/td&gt;
&lt;td&gt;yes, except with &lt;code dir=&quot;auto&quot;&gt;unsafe&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JSON with a missing field&lt;/td&gt;
&lt;td&gt;passes, typed as whatever you claimed&lt;/td&gt;
&lt;td&gt;the field quietly gets its zero value&lt;/td&gt;
&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;serde&lt;/code&gt; refuses it, unless it’s optional&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Extra fields in a response&lt;/td&gt;
&lt;td&gt;sent, unless something strips them&lt;/td&gt;
&lt;td&gt;only the struct’s fields are sent&lt;/td&gt;
&lt;td&gt;only the struct’s fields are sent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Errors&lt;/td&gt;
&lt;td&gt;anything can throw, and the type doesn’t say&lt;/td&gt;
&lt;td&gt;that a call can fail is in the signature&lt;/td&gt;
&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;Result&amp;#x3C;T, E&gt;&lt;/code&gt; in the signature&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Numbers&lt;/td&gt;
&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;number&lt;/code&gt; is a float: 64-bit ids need &lt;code dir=&quot;auto&quot;&gt;bigint&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;sized integers&lt;/td&gt;
&lt;td&gt;sized integers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CPU-heavy work&lt;/td&gt;
&lt;td&gt;one thread per process&lt;/td&gt;
&lt;td&gt;all cores&lt;/td&gt;
&lt;td&gt;all cores&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dependencies&lt;/td&gt;
&lt;td&gt;npm runs install scripts, Bun only for an allow list&lt;/td&gt;
&lt;td&gt;fetching or building runs no code&lt;/td&gt;
&lt;td&gt;build scripts run at build time&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;TypeScript’s types are erased before the code runs, so they’re claims, and
Bun or Node will run code whose claims don’t hold:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;div&gt;&lt;code&gt;&lt;span&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;order&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Order&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;span&gt;order&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;div&gt;&lt;code&gt;&lt;span&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;res&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Response&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;span&gt;res&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;json&lt;/span&gt;&lt;span&gt;()) &lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Order&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;// compiles, and nothing checked it&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;JSON&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;parse&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;{&quot;id&quot;: 9007199254740993}&apos;&lt;/span&gt;&lt;span&gt;).id; &lt;/span&gt;&lt;span&gt;// 9007199254740992&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Rust is stricter almost everywhere. Its compiler refuses whole classes of bugs,
and &lt;code dir=&quot;auto&quot;&gt;sqlx&lt;/code&gt; can even check each SQL query against a real database at build
time. Go is simpler and has a careful
&lt;a href=&quot;https://go.dev/blog/supply-chain&quot;&gt;supply chain&lt;/a&gt;, while npm runs install
scripts, which is how a worm spread through
&lt;a href=&quot;https://www.cisa.gov/news-events/alerts/2025/09/23/widespread-supply-chain-compromise-impacting-npm-ecosystem&quot;&gt;more than 500 packages&lt;/a&gt;
in 2025. If your team writes Go or Rust, these are good reasons to stay there.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;who-reads-the-code&quot;&gt;Who reads the code&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Then why TypeScript? Because of who reviews the code.&lt;/p&gt;
&lt;p&gt;Agents write a lot of our code now, but someone still reviews it before it
goes to production, and has to understand it. Tetsu was built that way: Claude
wrote most of its code, and I reviewed every change. José Valim, who created
Elixir, &lt;a href=&quot;https://x.com/josevalim/status/2108167477469327411&quot;&gt;wrote&lt;/a&gt; this week
that because of coding agents he reviews significantly more code than before.
And most of what that review is for isn’t a type error. In Stack Overflow’s
&lt;a href=&quot;https://stackoverflow.co/company/press/archive/stack-overflow-2025-developer-survey/&quot;&gt;2025 survey&lt;/a&gt;,
the most common frustration with AI tools was output that is almost right, and
45% of developers said debugging AI-generated code takes them longer.&lt;/p&gt;
&lt;p&gt;Code that is almost right is exactly what a compiler can’t see: a refund that
can exceed the order, a permission check on the wrong field, a status that
lets a cancelled order ship. Rust’s compiler doesn’t know your business rules
either.&lt;/p&gt;
&lt;p&gt;Cloudflare learned that in November 2025, when a large part of the web
returned errors for about three hours. A database permissions change made a
query return duplicate rows, the file that feeds Cloudflare’s bot detection
doubled in size, and it went over a limit of 200 features in the new proxy,
which is written in Rust. Rust had made the failure visible: it was an error
value the code had to handle. The code called &lt;code dir=&quot;auto&quot;&gt;unwrap()&lt;/code&gt; on it, and the proxy
&lt;a href=&quot;https://blog.cloudflare.com/18-november-2025-outage/&quot;&gt;panicked&lt;/a&gt;. The
compiler did its job. No compiler can tell you that a file which usually holds
about 60 features will one day hold more than 200. Someone who knows the
system can.&lt;/p&gt;
&lt;p&gt;Bun’s own team just showed what a strict compiler is best at: they
&lt;a href=&quot;https://bun.com/blog/bun-in-rust&quot;&gt;ported Bun from Zig to Rust&lt;/a&gt; with Claude
Code so that use-after-free and double-free bugs would become compile errors.
Those are memory bugs, and application code on a garbage-collected runtime
doesn’t have them. Its expensive bugs are in the business logic, and those are
caught by tests and by a person who knows the business and reads the code
fluently.&lt;/p&gt;
&lt;p&gt;You read fluently in the language you already write. If your team writes Go,
that’s Go, and you should pick Go. If it’s a web team that writes TypeScript
every day, and its front end too, it’s TypeScript. A model can write Rust for a
team that doesn’t know Rust, but then nobody on the team can really review it.&lt;/p&gt;
&lt;p&gt;So for a TypeScript team, the useful question is how to make TypeScript code
easy to review, and as safe as it can get.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;what-makes-code-easy-to-review&quot;&gt;What makes code easy to review&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Reviewing Tetsu’s code made one thing clear to me: code is easy to review when
everything that runs is visible where you read it. Every language has ways to
hide it. Rust’s derive and attribute macros generate code you never see. The
compiler checks it, but it isn’t the code you review, and reading it takes
&lt;code dir=&quot;auto&quot;&gt;cargo expand&lt;/code&gt;. Go reads struct tags, which are plain strings, through
reflection. TypeScript has decorators and DI containers, which decide at
runtime what runs and what gets injected.&lt;/p&gt;
&lt;p&gt;How much of that a project uses is the framework’s choice more than the
language’s. Tetsu uses none of it. It does use something TypeScript does better
than Go, and without the macros Rust needs: types computed from your own code,
such as a route’s parameters from its path, or a request body’s type from its
schema.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;how-tetsu-helps&quot;&gt;How Tetsu helps&lt;/h2&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;a-route-reads-top-to-bottom&quot;&gt;A route reads top to bottom&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;A route in Tetsu is one object: the method, the path, schemas for each part of
the request and response, the hooks that run around it, and the handler.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;auth&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; hook.&lt;/span&gt;&lt;span&gt;beforeParse&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;div&gt;&lt;code&gt;&lt;span&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;user&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;User&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;undefined&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;span&gt;user&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;div&gt;&lt;code&gt;&lt;span&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sessions&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;verify&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;token&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Promise&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;User&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;undefined&lt;/span&gt;&lt;span&gt;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;span&gt;sessions&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;verify&lt;/span&gt;&lt;span&gt;(ctx.&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;div&gt;&lt;code&gt;&lt;span&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt;: Request &lt;/span&gt;&lt;span&gt;&amp;#x26;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly cookies&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; Bun.CookieMap;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/span&gt;&lt;/code&gt;&lt;div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;The raw incoming request, always available as an escape hatch.&lt;/p&gt;
&lt;p&gt;On a request that matched a route, Bun&apos;s router delivers its own
request object carrying &lt;code&gt;cookies&lt;/code&gt; — a &lt;code&gt;Bun.CookieMap&lt;/code&gt; whose mutations
are applied to the response as &lt;code&gt;Set-Cookie&lt;/code&gt; automatically, with Bun&apos;s
defaults (&lt;code&gt;Path=/; SameSite=Lax&lt;/code&gt;). The field is optional because it
does not exist where Bun&apos;s router was not involved: the &lt;code&gt;404&lt;/code&gt; fallback
and unit-tested handlers. &lt;code&gt;ctx.out.headers.append(&quot;set-cookie&quot;, ...)&lt;/code&gt;
is the fallback that works everywhere.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;req&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;div&gt;&lt;code&gt;&lt;span&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;headers&lt;/span&gt;&lt;span&gt;: Headers&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/span&gt;&lt;/code&gt;&lt;div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;The &lt;strong&gt;&lt;code&gt;headers&lt;/code&gt;&lt;/strong&gt; read-only property of the with the request.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/Request/headers&quot;&gt;MDN Reference&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;headers&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;authorization&quot;&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;div&gt;&lt;code&gt;&lt;span&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;user&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;User&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;undefined&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;span&gt;user&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;throw&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;HttpError&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;401&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;div&gt;&lt;code&gt;&lt;span&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;user&lt;/span&gt;&lt;span&gt;: User&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;span&gt;user&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; };&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;refund&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;route&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;div&gt;&lt;code&gt;&lt;span&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;method&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;POST&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/span&gt;&lt;/code&gt;&lt;div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;The method this route answers.&lt;/p&gt;
&lt;p&gt;Kept as a literal rather than widened to&lt;/p&gt;
&lt;p&gt;Method&lt;/p&gt;
&lt;p&gt;: the method is
half of a route&apos;s identity, and an application that remembers its
routes — for a generated client, for tooling — needs to know which one
this is.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;method&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;POST&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;div&gt;&lt;code&gt;&lt;span&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;/orders/:id/refund&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/span&gt;&lt;/code&gt;&lt;div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Route path with &lt;code&gt;:param&lt;/code&gt; segments, e.g. &lt;code&gt;&quot;/orders/:id/cancel&quot;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Must start with &lt;code&gt;/&lt;/code&gt;, contain no empty segments and no trailing slash;
a malformed literal is a compile error.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;path&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;/orders/:id/refund&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;schema: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;params: z.&lt;/span&gt;&lt;span&gt;object&lt;/span&gt;&lt;span&gt;({ id: z.coerce.&lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;() }),&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;body: z.&lt;/span&gt;&lt;span&gt;object&lt;/span&gt;&lt;span&gt;({ amount: z.&lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;positive&lt;/span&gt;&lt;span&gt;() }),&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;response: { &lt;/span&gt;&lt;span&gt;200&lt;/span&gt;&lt;span&gt;: RefundDto },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;hooks: { beforeParse: [auth] },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;div&gt;&lt;code&gt;&lt;span&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;handler&lt;/span&gt;&lt;span&gt;: (&lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;user&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;User&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Request&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;#x26;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cookies&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Bun&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;CookieMap&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;server&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Bun&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Server&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;unknown&lt;/span&gt;&lt;span&gt;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;out&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Outgoing&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;#x26;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;DeclaredOutgoing&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;200&lt;/span&gt;&lt;span&gt;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;route&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;RouteInfo&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;startedAt&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;params&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;body&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;amount&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; Refund&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/span&gt;&lt;/code&gt;&lt;div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;The endpoint logic; &lt;code&gt;ctx&lt;/code&gt; is fully inferred, never annotate it.&lt;/p&gt;
&lt;p&gt;The return type is inferred rather than demanded, and checked twice
over. Against the route&apos;s own contract, by the&lt;/p&gt;
&lt;p&gt;HandlerResult&lt;/p&gt;
&lt;p&gt;bound on &lt;code&gt;R&lt;/code&gt;: answering with something &lt;code&gt;response&lt;/code&gt; never declared is a
compile error that says so, instead of a structural diff against
&lt;code&gt;Response&lt;/code&gt;. And against what the framework can serialize at all, by
the intersected&lt;/p&gt;
&lt;p&gt;ValidateResult&lt;/p&gt;
&lt;p&gt;: a stream handed over bare is
refused whether or not the route declared anything, because that is
the case no contract covers — without a &lt;code&gt;response&lt;/code&gt; schema
&lt;code&gt;HandlerResult&lt;/code&gt; is &lt;code&gt;unknown&lt;/code&gt; and accepts every value there is.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;handler&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;: (&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;div&gt;&lt;code&gt;&lt;span&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;user&lt;/span&gt;&lt;span&gt;: User;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt;: Request &lt;/span&gt;&lt;span&gt;&amp;#x26;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly cookies&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; Bun.CookieMap;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;server&lt;/span&gt;&lt;span&gt;: Bun.Server&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;unknown&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;out&lt;/span&gt;&lt;span&gt;: Outgoing &lt;/span&gt;&lt;span&gt;&amp;#x26;&lt;/span&gt;&lt;span&gt; DeclaredOutgoing&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;200&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;route&lt;/span&gt;&lt;span&gt;: RouteInfo;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;startedAt&lt;/span&gt;&lt;span&gt;: number;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;params&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;: number;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;body&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;amount&lt;/span&gt;&lt;span&gt;: number;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;div&gt;&lt;code&gt;&lt;span&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;refunds&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;create&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;by&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;User&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;orderId&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;amount&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Refund&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;span&gt;refunds&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;create&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;div&gt;&lt;code&gt;&lt;span&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;user&lt;/span&gt;&lt;span&gt;: User;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt;: Request &lt;/span&gt;&lt;span&gt;&amp;#x26;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly cookies&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; Bun.CookieMap;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;server&lt;/span&gt;&lt;span&gt;: Bun.Server&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;unknown&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;out&lt;/span&gt;&lt;span&gt;: Outgoing &lt;/span&gt;&lt;span&gt;&amp;#x26;&lt;/span&gt;&lt;span&gt; DeclaredOutgoing&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;200&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;route&lt;/span&gt;&lt;span&gt;: RouteInfo;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;startedAt&lt;/span&gt;&lt;span&gt;: number;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;params&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;: number;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;body&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;amount&lt;/span&gt;&lt;span&gt;: number;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;div&gt;&lt;code&gt;&lt;span&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;user&lt;/span&gt;&lt;span&gt;: User&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;span&gt;user&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;div&gt;&lt;code&gt;&lt;span&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;user&lt;/span&gt;&lt;span&gt;: User;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt;: Request &lt;/span&gt;&lt;span&gt;&amp;#x26;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly cookies&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; Bun.CookieMap;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;server&lt;/span&gt;&lt;span&gt;: Bun.Server&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;unknown&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;out&lt;/span&gt;&lt;span&gt;: Outgoing &lt;/span&gt;&lt;span&gt;&amp;#x26;&lt;/span&gt;&lt;span&gt; DeclaredOutgoing&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;200&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;route&lt;/span&gt;&lt;span&gt;: RouteInfo;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;startedAt&lt;/span&gt;&lt;span&gt;: number;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;params&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;: number;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;body&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;amount&lt;/span&gt;&lt;span&gt;: number;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;div&gt;&lt;code&gt;&lt;span&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;params&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;: number;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;span&gt;params&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;div&gt;&lt;code&gt;&lt;span&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;: number&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;span&gt;id&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;div&gt;&lt;code&gt;&lt;span&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;user&lt;/span&gt;&lt;span&gt;: User;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt;: Request &lt;/span&gt;&lt;span&gt;&amp;#x26;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly cookies&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; Bun.CookieMap;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;server&lt;/span&gt;&lt;span&gt;: Bun.Server&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;unknown&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;out&lt;/span&gt;&lt;span&gt;: Outgoing &lt;/span&gt;&lt;span&gt;&amp;#x26;&lt;/span&gt;&lt;span&gt; DeclaredOutgoing&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;200&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;route&lt;/span&gt;&lt;span&gt;: RouteInfo;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;startedAt&lt;/span&gt;&lt;span&gt;: number;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;params&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;: number;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;body&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;amount&lt;/span&gt;&lt;span&gt;: number;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;div&gt;&lt;code&gt;&lt;span&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;body&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;amount&lt;/span&gt;&lt;span&gt;: number;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;span&gt;body&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;div&gt;&lt;code&gt;&lt;span&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;amount&lt;/span&gt;&lt;span&gt;: number&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;span&gt;amount&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;A reviewer sees who can call it, what it accepts, what it returns and what it
does. That’s also what lets them see what the route doesn’t do: nothing here
stops a refund larger than the order, unless &lt;code dir=&quot;auto&quot;&gt;refunds.create&lt;/code&gt; checks it.
That’s the almost-right bug from earlier. Neither the compiler nor the schema
can see it, but a reviewer with the whole route in front of them can ask.&lt;/p&gt;
&lt;p&gt;Hooks sit in named slots that always run in the same order, so there’s no
&lt;code dir=&quot;auto&quot;&gt;next()&lt;/code&gt; chain to trace. Anything else that runs for this route sits on its
group or the app, in the same form. There are no decorators, no container and
no plugins: a controller gets its dependencies as function arguments, and the
wiring is ordinary code in one file.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;types-show-only-what-exists&quot;&gt;Types show only what exists&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;ctx&lt;/code&gt; is never annotated. A field is in its type exactly when it exists at that
point: &lt;code dir=&quot;auto&quot;&gt;ctx.params.id&lt;/code&gt; because the path has &lt;code dir=&quot;auto&quot;&gt;:id&lt;/code&gt;, a number because the schema
converts it, &lt;code dir=&quot;auto&quot;&gt;ctx.body&lt;/code&gt; because the route declares a body, &lt;code dir=&quot;auto&quot;&gt;ctx.user&lt;/code&gt; because
&lt;code dir=&quot;auto&quot;&gt;auth&lt;/code&gt; returned it. Remove &lt;code dir=&quot;auto&quot;&gt;auth&lt;/code&gt;, and the handler stops compiling:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;route&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;div&gt;&lt;code&gt;&lt;span&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;method&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;GET&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/span&gt;&lt;/code&gt;&lt;div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;The method this route answers.&lt;/p&gt;
&lt;p&gt;Kept as a literal rather than widened to&lt;/p&gt;
&lt;p&gt;Method&lt;/p&gt;
&lt;p&gt;: the method is
half of a route&apos;s identity, and an application that remembers its
routes — for a generated client, for tooling — needs to know which one
this is.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;method&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;GET&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;div&gt;&lt;code&gt;&lt;span&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;/reports&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/span&gt;&lt;/code&gt;&lt;div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Route path with &lt;code&gt;:param&lt;/code&gt; segments, e.g. &lt;code&gt;&quot;/orders/:id/cancel&quot;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Must start with &lt;code&gt;/&lt;/code&gt;, contain no empty segments and no trailing slash;
a malformed literal is a compile error.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;path&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;/reports&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;div&gt;&lt;code&gt;&lt;span&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;handler&lt;/span&gt;&lt;span&gt;: (&lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Request&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;#x26;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cookies&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Bun&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;CookieMap&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;server&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Bun&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Server&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;unknown&lt;/span&gt;&lt;span&gt;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;out&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Outgoing&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;route&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;RouteInfo&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;startedAt&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;params&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; string[]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/span&gt;&lt;/code&gt;&lt;div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;The endpoint logic; &lt;code&gt;ctx&lt;/code&gt; is fully inferred, never annotate it.&lt;/p&gt;
&lt;p&gt;The return type is inferred rather than demanded, and checked twice
over. Against the route&apos;s own contract, by the&lt;/p&gt;
&lt;p&gt;HandlerResult&lt;/p&gt;
&lt;p&gt;bound on &lt;code&gt;R&lt;/code&gt;: answering with something &lt;code&gt;response&lt;/code&gt; never declared is a
compile error that says so, instead of a structural diff against
&lt;code&gt;Response&lt;/code&gt;. And against what the framework can serialize at all, by
the intersected&lt;/p&gt;
&lt;p&gt;ValidateResult&lt;/p&gt;
&lt;p&gt;: a stream handed over bare is
refused whether or not the route declared anything, because that is
the case no contract covers — without a &lt;code&gt;response&lt;/code&gt; schema
&lt;code&gt;HandlerResult&lt;/code&gt; is &lt;code&gt;unknown&lt;/code&gt; and accepts every value there is.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;handler&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;: (&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;div&gt;&lt;code&gt;&lt;span&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt;: Request &lt;/span&gt;&lt;span&gt;&amp;#x26;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly cookies&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; Bun.CookieMap;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;server&lt;/span&gt;&lt;span&gt;: Bun.Server&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;unknown&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;out&lt;/span&gt;&lt;span&gt;: Outgoing;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;route&lt;/span&gt;&lt;span&gt;: RouteInfo;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;startedAt&lt;/span&gt;&lt;span&gt;: number;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;params&lt;/span&gt;&lt;span&gt;: {};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;reportsFor&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;div&gt;&lt;code&gt;&lt;span&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt;: Request &lt;/span&gt;&lt;span&gt;&amp;#x26;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly cookies&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; Bun.CookieMap;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;server&lt;/span&gt;&lt;span&gt;: Bun.Server&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;unknown&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;out&lt;/span&gt;&lt;span&gt;: Outgoing;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;route&lt;/span&gt;&lt;span&gt;: RouteInfo;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;startedAt&lt;/span&gt;&lt;span&gt;: number;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;params&lt;/span&gt;&lt;span&gt;: {};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&lt;span&gt;user&lt;/span&gt;&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;Error ts(2339)  ― &lt;/span&gt;&lt;span&gt;Property &apos;user&apos; does not exist on type &apos;{ readonly req: Request &amp;#x26; { readonly cookies?: CookieMap | undefined; }; readonly server: Server&amp;#x3C;unknown&gt;; readonly out: Outgoing; readonly route: RouteInfo; readonly startedAt: number; readonly params: {}; }&apos;.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;A reviewer doesn’t have to check by eye whether auth ran before this handler.
The compiler already did.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;boundaries-are-parsed-in-one-place&quot;&gt;Boundaries are parsed in one place&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The schemas are the checks. A request with a missing or malformed field gets
a &lt;code dir=&quot;auto&quot;&gt;422&lt;/code&gt; that lists every issue, and the handler never runs. This is the old
advice to &lt;a href=&quot;https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/&quot;&gt;parse, don’t validate&lt;/a&gt;:
one schema at the edge instead of checks spread through the handler, and one
place for a reviewer to look.&lt;/p&gt;
&lt;p&gt;Responses are parsed too, which closes one of the gaps from the table.
TypeScript lets an object with extra fields pass for a type with fewer, so a
stored user with a &lt;code dir=&quot;auto&quot;&gt;passwordHash&lt;/code&gt; passes for a public user. The response schema
runs on the way out, and its output is what gets sent. With Zod or Valibot,
that drops the hash. ArkType and TypeBox have to be told to:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;PublicUser&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; z.&lt;/span&gt;&lt;span&gt;object&lt;/span&gt;&lt;span&gt;({ id: z.&lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;(), name: z.&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;() });&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;route&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;div&gt;&lt;code&gt;&lt;span&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;method&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;GET&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/span&gt;&lt;/code&gt;&lt;div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;The method this route answers.&lt;/p&gt;
&lt;p&gt;Kept as a literal rather than widened to&lt;/p&gt;
&lt;p&gt;Method&lt;/p&gt;
&lt;p&gt;: the method is
half of a route&apos;s identity, and an application that remembers its
routes — for a generated client, for tooling — needs to know which one
this is.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;method&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;GET&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;div&gt;&lt;code&gt;&lt;span&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;/users/:id&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/span&gt;&lt;/code&gt;&lt;div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Route path with &lt;code&gt;:param&lt;/code&gt; segments, e.g. &lt;code&gt;&quot;/orders/:id/cancel&quot;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Must start with &lt;code&gt;/&lt;/code&gt;, contain no empty segments and no trailing slash;
a malformed literal is a compile error.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;path&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;/users/:id&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;schema: { params: z.&lt;/span&gt;&lt;span&gt;object&lt;/span&gt;&lt;span&gt;({ id: z.coerce.&lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;() }), response: { &lt;/span&gt;&lt;span&gt;200&lt;/span&gt;&lt;span&gt;: PublicUser } },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;div&gt;&lt;code&gt;&lt;span&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;handler&lt;/span&gt;&lt;span&gt;: (&lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;out&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Outgoing&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;#x26;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;DeclaredOutgoing&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;200&lt;/span&gt;&lt;span&gt;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Request&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;#x26;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cookies&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Bun&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;CookieMap&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;server&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Bun&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Server&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;unknown&lt;/span&gt;&lt;span&gt;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;route&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;RouteInfo&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;startedAt&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;readonly&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;params&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; StoredUser&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/span&gt;&lt;/code&gt;&lt;div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;The endpoint logic; &lt;code&gt;ctx&lt;/code&gt; is fully inferred, never annotate it.&lt;/p&gt;
&lt;p&gt;The return type is inferred rather than demanded, and checked twice
over. Against the route&apos;s own contract, by the&lt;/p&gt;
&lt;p&gt;HandlerResult&lt;/p&gt;
&lt;p&gt;bound on &lt;code&gt;R&lt;/code&gt;: answering with something &lt;code&gt;response&lt;/code&gt; never declared is a
compile error that says so, instead of a structural diff against
&lt;code&gt;Response&lt;/code&gt;. And against what the framework can serialize at all, by
the intersected&lt;/p&gt;
&lt;p&gt;ValidateResult&lt;/p&gt;
&lt;p&gt;: a stream handed over bare is
refused whether or not the route declared anything, because that is
the case no contract covers — without a &lt;code&gt;response&lt;/code&gt; schema
&lt;code&gt;HandlerResult&lt;/code&gt; is &lt;code&gt;unknown&lt;/code&gt; and accepts every value there is.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;handler&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;: (&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;div&gt;&lt;code&gt;&lt;span&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;out&lt;/span&gt;&lt;span&gt;: Outgoing &lt;/span&gt;&lt;span&gt;&amp;#x26;&lt;/span&gt;&lt;span&gt; DeclaredOutgoing&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;200&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt;: Request &lt;/span&gt;&lt;span&gt;&amp;#x26;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly cookies&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; Bun.CookieMap;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;server&lt;/span&gt;&lt;span&gt;: Bun.Server&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;unknown&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;route&lt;/span&gt;&lt;span&gt;: RouteInfo;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;startedAt&lt;/span&gt;&lt;span&gt;: number;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;params&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;: number;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;div&gt;&lt;code&gt;&lt;span&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;users&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;find&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StoredUser&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;span&gt;users&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;find&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;div&gt;&lt;code&gt;&lt;span&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;out&lt;/span&gt;&lt;span&gt;: Outgoing &lt;/span&gt;&lt;span&gt;&amp;#x26;&lt;/span&gt;&lt;span&gt; DeclaredOutgoing&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;200&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt;: Request &lt;/span&gt;&lt;span&gt;&amp;#x26;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly cookies&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; Bun.CookieMap;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;server&lt;/span&gt;&lt;span&gt;: Bun.Server&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;unknown&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;route&lt;/span&gt;&lt;span&gt;: RouteInfo;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;startedAt&lt;/span&gt;&lt;span&gt;: number;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;readonly &lt;/span&gt;&lt;span&gt;params&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;: number;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;div&gt;&lt;code&gt;&lt;span&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;params&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;: number;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;span&gt;params&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;div&gt;&lt;code&gt;&lt;span&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;: number&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;span&gt;id&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;), &lt;/span&gt;&lt;span&gt;// a stored user, passwordHash included&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// GET /users/1 → 200 {&quot;id&quot;:1,&quot;name&quot;:&quot;Ada&quot;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;docs-come-from-the-code&quot;&gt;Docs come from the code&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The OpenAPI document is built from the same routes and schemas, so a reviewer
who approves a schema change has approved the docs too. Tetsu’s own
documentation is written for agents as well as people: every page is also
served as Markdown, all of it is in one file at
&lt;a href=&quot;https://tetsujs.com/llms-full.txt&quot;&gt;&lt;code dir=&quot;auto&quot;&gt;/llms-full.txt&lt;/code&gt;&lt;/a&gt;, and the packages ship TSDoc that editors
and agents read from &lt;code dir=&quot;auto&quot;&gt;node_modules&lt;/code&gt;. An agent that reads the right docs writes
code that’s closer to right, which leaves less for the reviewer.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;why-not-hono-or-elysia&quot;&gt;Why not Hono or Elysia&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Both are good, and both infer types from the path and from schemas. Where they
differ from Tetsu is how the code around a handler is put together, and that’s
what a reviewer reads. In Hono, middleware wraps the handler with &lt;code dir=&quot;auto&quot;&gt;next()&lt;/code&gt;, and
what runs for a route depends on the order of the &lt;code dir=&quot;auto&quot;&gt;app.use()&lt;/code&gt; calls. In
Elysia, the app is a chain of method calls, each extending the type of the
next, and a plugin’s scope decides how far its hooks reach. Both are more
flexible than Tetsu.&lt;/p&gt;
&lt;p&gt;Tetsu trades that flexibility for one shape: hooks in fixed slots, listed on
the route, its group or the app, and no plugins. It costs more typing, since
each route lists its own hooks, and it gives up things the others do well.
Hono runs on almost any runtime, and Elysia’s Eden gives the front end the
server’s types directly. &lt;a href=&quot;https://tetsujs.com/docs/more/comparison/&quot;&gt;Comparison&lt;/a&gt; has the details.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;what-it-doesnt-fix&quot;&gt;What it doesn’t fix&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;A framework can make TypeScript safer at the HTTP boundary, but not stricter
everywhere. Errors still aren’t in any signature, numbers are still floats,
CPU-heavy work still needs a worker, and a database row is still whatever the
driver returned unless you parse it too. Tetsu has a limit of its own: hooks
mounted on a group run for its routes but don’t add to their types, so a
handler that reads &lt;code dir=&quot;auto&quot;&gt;ctx.user&lt;/code&gt; needs &lt;code dir=&quot;auto&quot;&gt;auth&lt;/code&gt; on its own route.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;where-typescript-on-the-server-is-going&quot;&gt;Where TypeScript on the server is going&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The first row of the table is closing. Bun is adding a type checker of its own,
&lt;a href=&quot;https://bun.com/docs/runtime/check&quot;&gt;&lt;code dir=&quot;auto&quot;&gt;bun check&lt;/code&gt;&lt;/a&gt;, ported from typescript-go to
Rust and already in canary builds. &lt;code dir=&quot;auto&quot;&gt;bun --check server.ts&lt;/code&gt; checks the code before running
it, and &lt;code dir=&quot;auto&quot;&gt;bun test --check&lt;/code&gt; checks it before the tests, so code with a type
error no longer has to run at all. I tried the canary build on Tetsu’s
repository: on the same 1,588 files, it reported the same errors as &lt;code dir=&quot;auto&quot;&gt;tsc&lt;/code&gt;,
with the same messages, in 0.22 seconds against 0.8 for TypeScript 7, on an
M5 Pro. The TypeScript compiler itself was rewritten in Go, and TypeScript 7
came out in July
&lt;a href=&quot;https://www.infoworld.com/article/4196378/go-based-typescript-7-0-arrives.html&quot;&gt;about ten times faster&lt;/a&gt;.
For a team that reviews TypeScript, that means the type check can run on every
save and every test run, not only in CI.&lt;/p&gt;
&lt;p&gt;There’s money behind it too. Bun had no revenue when Anthropic bought it in
December 2025. Claude Code ships to millions of users as a Bun executable, so
Anthropic has a direct stake in Bun’s quality, and Bun’s
&lt;a href=&quot;https://bun.com/blog/bun-joins-anthropic&quot;&gt;own post&lt;/a&gt; about the deal says its
roadmap still includes replacing Node.js as the default runtime on the server.
Since then, &lt;a href=&quot;https://bun.com/blog/bun-v1.4&quot;&gt;Bun 1.4&lt;/a&gt; fixed more than 2,900
issues, the runtime itself was rewritten in Rust, and the &lt;code dir=&quot;auto&quot;&gt;bun&lt;/code&gt; package on npm
had &lt;a href=&quot;https://api.npmjs.org/downloads/point/2026-09-01:2026-09-30/bun&quot;&gt;15 million downloads&lt;/a&gt;
in September 2026, ten times
&lt;a href=&quot;https://api.npmjs.org/downloads/point/2025-09-01:2025-09-30/bun&quot;&gt;more than a year before&lt;/a&gt;.
I have no ties to Anthropic, for the record.&lt;/p&gt;
&lt;p&gt;Tetsu runs only on Bun, so if Bun stalls, so does Tetsu. All of this lowers
that risk without removing it.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;when-id-pick-which&quot;&gt;When I’d pick which&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;If your team writes Go or Rust, pick Go or Rust, for the same reason I picked
TypeScript: you’ll review that code best.&lt;/p&gt;
&lt;p&gt;If your team writes TypeScript, especially on the front end, TypeScript on the
server is a reasonable choice in 2026, if you do four things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Run &lt;code dir=&quot;auto&quot;&gt;tsc --noEmit&lt;/code&gt; in CI, or &lt;code dir=&quot;auto&quot;&gt;bun check&lt;/code&gt; once it’s in a stable Bun release.&lt;/li&gt;
&lt;li&gt;Turn on &lt;code dir=&quot;auto&quot;&gt;strict&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;noUncheckedIndexedAccess&lt;/code&gt;, and ban &lt;code dir=&quot;auto&quot;&gt;any&lt;/code&gt; in the linter,
for example with Biome’s &lt;code dir=&quot;auto&quot;&gt;noExplicitAny&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Parse every boundary with a schema: requests, responses, database rows,
other services’ replies and configuration.&lt;/li&gt;
&lt;li&gt;Choose tools that keep the code readable: no hidden wiring, nothing that runs
without being visible where you read.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That’s why I wrote Tetsu in TypeScript. Agents can write the code, but someone
still has to understand it, and the language you understand best is the one
you already write.&lt;/p&gt;
&lt;p&gt;Tetsu is MIT licensed. The &lt;a href=&quot;https://tetsujs.com/docs/quick-start/&quot;&gt;quick start&lt;/a&gt; builds a first
app with a test, and the code is on &lt;a href=&quot;https://github.com/tetsujs/tetsu&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
</content:encoded></item></channel></rss>