Go and TypeScript: Strict Types for AI-Assisted Coding

Because the compiler or type checker gives an AI agent an instant, machine-readable feedback loop. When a model hallucinates a method that does not exist or an impossible combination of fields, a statically typed language rejects it at build time in under a second, so the agent can self-correct before any code runs. That turns verification — the part of the job AI shifted onto humans — into something the toolchain does automatically.
Not in the raw benchmark sense. On the peer-reviewed Multi-SWE-bench, Python leads with a 52.2% best resolved rate while Go sits near the bottom at 7.5%, mostly because pass rate tracks how much training data a language has, not how strict its types are. What strict typing improves is the cost of each attempt and each verification — how cheaply a mistake is caught — which the single-shot leaderboard barely measures.
gofmt gives every Go file one canonical shape, so the code a model trains on looks the same regardless of who wrote it. That tighter, more consistent distribution means the model returns idiomatic Go in fewer shots and has fewer plausible-but-wrong ways to express an idea. Combined with Go's compatibility promise, the model is never generating against a moving target.
A discriminated union models a value as one of several fixed shapes rather than a bag of optional fields. Instead of letting the agent guess which field combinations are legal, it makes the illegal ones fail to compile. TypeScript then only lets the agent read a field after a matching type guard, so it physically cannot access data that is not there — which means fewer wrong parsers and fewer runtime bugs.
No. A SWE-bench pass rate blends the model, the agent framework, how many tasks the benchmark could gather, and the size of the training corpus, so it is not a language-quality score. Treat it as evidence about the benchmark itself. The durable property you actually get from a language is its feedback loop — how quickly and cheaply its toolchain rejects wrong code — and that is what to optimise for.

Key Takeaway
Strict, statically typed languages like Go and TypeScript suit AI-assisted coding because the compiler and type checker hand an agent an instant feedback loop: a hallucinated method or an impossible state is rejected at build time, in under a second, so the agent corrects itself before any code runs — moving verification, now the human bottleneck, into the toolchain.
Two articles landed in my feeds about a week apart and made the same argument from opposite ends of the language spectrum. Google's Go team wrote that Go is an ideal language for AI-assisted software engineering; a few months earlier Pierre-Marie Dartus wrote that TypeScript quietly does the same job for the JavaScript world. I had felt it without naming it: my agents finished Go and TypeScript tasks with far less hand-holding than they needed in a loosely typed codebase.
This post is about why that happens, and where the claim falls apart. I build ERP systems in TypeScript and NestJS and reach for Go on the infrastructure side, so what follows is a working developer's read of two strong essays, a peer-reviewed benchmark, and a study on type-constrained code generation — not a language war. I also show a benchmark result that argues against the headline, because it is the most useful part.
The shift the Go team describes is the one every argument here rests on. For a long time most lines of code were written by hand; now we ask an agent to generate large stretches and spend our own time reading, correcting and verifying what it produced. The scarce resource stopped being typing speed and became trust — how quickly a human, or the next agent, can be sure a change is safe to ship.
That reframes what a language is for. A language optimised for writability — terse, clever, many ways to say one thing — was tuned for the part machines now do. A language optimised for readability and verification was tuned for the part that is suddenly the whole job. Go was built for software engineering over programming, in its team's words, and that older bet turns out to match what AI-assisted work needs.
The mechanism is simpler than the marketing. A model predicts plausible code, and plausible code includes methods that were never defined and fields that do not exist on a value. In a statically typed language the compiler or type checker catches exactly that class of mistake, immediately, and says so in one line:
package main
import (
"fmt"
"strings"
)
func main() {
// The model reached for a method that sounds right but was never defined.
fmt.Println(strings.Reverse("gopher"))
}
// $ go build ./...
// ./main.go:10:26: undefined: strings.Reverse
//
// The build fails in well under a second. The agent reads that one line,
// drops the invented call, and writes the reversal by hand — before a single
// test runs, before the program is ever executed.That one line is a free training signal. The agent reads the error, deletes the invented call and tries again — a self-correction loop that runs in the editor or the build, before a test executes and long before the code ships. The type-constrained code-generation study by Mundler and colleagues measured the ceiling on this: constraining generation to well-typed programs more than halved compilation errors and raised functional correctness across synthesis, translation and repair. Dartus reports the same thing by hand — after tightening his type definitions, his agent generated correct code in fewer attempts.

If your agent keeps writing subtly wrong code against a library, do not just retry. Tighten the types it codes against, or paste the library's own type definitions into context — a narrower type rejects more wrong answers before the model ever shows them to you.
Go's second advantage is uniformity, and it is deliberate. The language rejects the syntactic magic other languages celebrate and ships a formatter, gofmt, that gives every file one canonical shape. For a human team that means less bikeshedding; for a model it does three things at once:
Compilation speed closes the loop. Go's build is fast enough — orders of magnitude quicker than the heavier statically typed languages, by Google's account — that the reject-and-retry cycle costs the agent a second, not a coffee break. A feedback loop only shapes behaviour if it is fast; a slow one gets skipped.
TypeScript reaches the same place from the other direction: it wraps the most-used language on the web in a type system precise enough to encode intent. Dartus's clearest example is a discriminated union. Model an annotation as a bag of optional fields and the agent has to guess which combinations are legal; model it as a union of fixed shapes and the illegal combinations simply stop compiling.
// Wrong: optional fields let the model invent impossible states.
interface Annotation {
kind: "highlight" | "note";
note?: string; // present on a note... or on a highlight? the model guesses
quote?: string; // and a guess is a bug you find at runtime, or never
color?: string;
}
// Right: a discriminated union. The shape of each case is fixed.
type Annotation =
| { kind: "highlight"; quote: string; color: string }
| { kind: "note"; quote: string; note: string };
// Now annotation.note only type-checks after a kind === "note" guard,
// so the agent physically cannot read a field that isn't there. tsc rejects
// the parser it would otherwise have written — in the editor, before you run it.The knock-on effect is about context, not just correctness. Just as a typed signature lets a human work on one file without holding the whole system in their head, it lets an agent reason about a slice of the codebase without pulling the entire project into its context window — Dartus's point, and it matches how the good agents behave. Two more things lowered the barrier for me: recent Node versions strip types natively, so TypeScript runs without a separate build step, and the editor's language server feeds errors straight back to agents that retry on the lint automatically.
Hallucinated imports are their own failure mode: a model confidently requires a package that does not exist, or worse, one a squatter has since registered under that guessed name. A large, batteries-included standard library is the cheapest defence, because it gives the model a correct, well-trained default for the common case and less reason to reach for a third-party name it half-remembers.
Go leans on this hard: its standard library covers most of what a service needs, and govulncheck reads the call graph to report only the vulnerabilities you actually reach — low-noise feedback an agent can act on. Go's module checksum database and mirror also make a dependency's bytes verifiable, so a swapped package gets caught.
TypeScript cannot match that from the language, so the ecosystem does the work — unevenly. Dartus found an agent struggled against a niche parser with thirty thousand weekly downloads and would likely have sailed through the fifty-million-download alternative, purely because the popular library is better represented in training data and docs. The lesson is portable: with an AI agent, the boring, well-documented, widely-used dependency is not just safer, it is measurably easier for the model to use correctly.

Here is the honest part. If strict typing made models better coders outright, the multilingual benchmarks would show it, and they do not. On Multi-SWE-bench — a peer-reviewed set of real GitHub issues across seven languages, resolved by the strongest models and agent frameworks of 2025 — the best resolved rate per language looks like this:
| Language | Best resolved rate | What the number actually tracks |
|---|---|---|
| Python | 52.2% | Far more training data than any other — dynamic, and still on top |
| Java | 23.4% | Statically typed and heavily represented — data plus types |
| Rust | 15.9% | Strict types and a strong compiler, but a sparse corpus |
| TypeScript | 11.6% | Typed, yet a vast and inconsistent ecosystem to model |
| Go | 7.5% | Typed and simple — and near the bottom on this benchmark |
Go last is not a typo, and it is the reason to stay careful. A single-shot resolved rate is dominated by how much of a language the model has seen and how many usable tasks the benchmark could gather, not by how strict its types are. Python wins on corpus size; Go's low score reflects a thinner slice of tasks, not a worse language. What strict typing changes is the thing this metric barely measures — the cost of each attempt and each verification — which is precisely the cost AI shifted onto us. The essays and the type-constrained study measure that loop; the leaderboard measures something else.
Do not pick a language for your next project off a SWE-bench column, in either direction. The pass rate blends model, agent framework, task supply and corpus size; it is not a language-quality score. Treat it as evidence about the benchmark, and treat the feedback loop as the property you actually get to keep.
So the rule I now work by is narrow and defensible: strict, statically typed languages do not make an AI a better programmer, but they make its mistakes cheaper to catch — and in a world where I review far more than I write, cheap-to-catch is what I am buying. Reach for Go where a small language and a fast compiler pay off, reach for TypeScript to put guardrails on JavaScript, and write the tightest types you can afford. The compiler is the one reviewer that never gets tired.
Sources and further reading