Get your free personalized podcast brief

We scan new podcasts and send you the top 5 insights daily.

For a project with a massive user base like TypeScript, a full rewrite is toxic because it inevitably introduces breaking changes. The team chose to port the existing code to Go, preserving the exact algorithms and behavior to ensure backward compatibility and keep the ecosystem happy.

Related Insights

When migrating a large codebase, asking an LLM to perform the translation is risky due to its non-deterministic nature. A better approach is to enlist AI to help write a custom, deterministic translation program. This contains the AI's stochasticness to the tool-building phase, not the execution phase.

TypeScript's success over its competitor, Flow, was partly due to being "self-hosted" (written in TypeScript). This lowered the barrier for the JavaScript community to contribute. In contrast, Flow was written in OCaml, requiring contributors to learn a completely different language and ecosystem.

When asked to modify or rewrite functionality, LLMs often attempt to preserve compatibility with previous versions, even on greenfield projects. This defensive behavior can lead to overly complex code and technical debt. Developers must explicitly state that backward compatibility is not a requirement.

For years, updating legacy systems like bank mainframes running COBOL was prohibitively expensive. Modern AI agents are now so proficient at code migration that these projects are finally feasible. One engineer migrated the entire Bun codebase to a new language in just 11 days, a task that previously would have taken a team a year.

Zach Lloyd advises against rewriting code for early-stage startups, calling it a 'horrible idea' that pauses critical momentum. This intensive effort is only justified for products at massive scale, like Google Sheets, where perfecting the experience for over 100 million users warrants the multi-year engineering investment.

Beyond catching compile-time errors, a strong static type system's main benefit is making large, aging codebases maintainable. Dynamically typed programs can become immutable as original authors leave. With static types, a developer can fearlessly refactor a 35-year-old codebase by letting the compiler guide them to all necessary changes.

A full-codebase rewrite using AI, like Bun's Zig-to-Rust migration, is risky. It exchanges a set of known bugs for new, unknown ones. Users become the unfortunate discoverers of these issues, as even comprehensive test suites can't capture every implicit behavior (Hiram's Law).

Go was selected for the native port because its built-in garbage collection could handle the TypeScript compiler's many circular data structures. Rust's borrow checker would have required a fundamental redesign of these structures, violating the team's "port, don't rewrite" principle.

The idea for TypeScript came when a team wanted to transpile C# to JavaScript solely to get better tooling. Anders Hejlsberg realized the core problem wasn't JavaScript, but its poor developer experience. This led to improving JavaScript with a type system rather than trying to replace it.

The primary motivation for rewriting the TypeScript compiler in Go wasn't just the 2-3x performance gain. It was to escape JavaScript's single-threaded model and access shared memory concurrency, which is essential for utilizing modern multi-core CPUs and couldn't be achieved with web workers.