What Four Decades of Language Design Teach About Building for Scale

Anders Hejlsberg has shaped how a generation of developers write software—as the creator of Turbo Pascal and Delphi, lead architect of C#, and designer of TypeScript. In a recent conversation, he reflected on what happens when tools outgrow their origins: where performance ceilings appear, why open source became unavoidable, and how AI is shifting what a programming tool is actually for.

The patterns that emerge apply well beyond language design. They’re about building systems that survive contact with real-world scale.

The Feedback Loop Is the Product

Hejlsberg’s earliest instincts came from a time of extreme constraints. On 64KB machines, “you could keep it all in your head,” he recalls. There was no room for abstraction that didn’t pull its weight.

When you typed your code, you wanted to run it immediately.

Turbo Pascal’s impact wasn’t from Pascal itself—it was from shortening the loop. Edit, compile, run, fail, repeat, without touching disk or waiting for tooling. The same idea resurfaces decades later in TypeScript, much of whose value comes not from the language but from its tooling: incremental checking, fast partial results, and language services that respond quickly even on large codebases.

Fast feedback changes behavior. Errors surface sooner, so developers experiment more and refactor more confidently. When feedback is slow, teams compensate with conventions, workarounds, and process overhead. The lesson is direct: tools that shorten the distance between writing code and understanding its consequences earn trust; tools that introduce latency get sidelined, however powerful they are.

Scaling Means Surrendering Personal Taste

Hejlsberg’s hardest adjustment, especially during the Delphi years, wasn’t technical—it was learning to let go of personal preferences.

You have to accept that things get done differently than you would have preferred. Fixing it would not really change the behavior anyway.

C# didn’t emerge from a clean slate. It came from conflicting demands: Visual Basic developers wanted approachability, C++ developers wanted power, and Windows demanded pragmatism. The result wasn’t theoretical purity—it was a language enough people could use effectively. Languages don’t succeed because they’re perfectly designed; they succeed because they accommodate how teams actually work.

Why TypeScript Worked with JavaScript Instead of Against It

TypeScript exists because JavaScript succeeded beyond what dynamic typing comfortably supports. Early coping strategies were extreme—some teams compiled entirely different languages to JavaScript just to get static analysis and refactoring tools.

Hejlsberg never found that approach realistic. A new language in 2012 would have required not just a compiler but years of editors, debuggers, and community adoption. Instead, TypeScript extended JavaScript in place, inheriting its flaws while making large-scale development more tractable.

The broader principle: improvements that respect existing workflows spread; improvements that demand wholesale replacement rarely do. Meaningful progress often means making systems you already depend on more capable, not starting over.

Open Source Is About Visible Decisions, Not Just Visible Code

TypeScript’s early releases were nominally open source, but development stayed largely closed. That changed in 2014 with a move to GitHub and a fully public process: features proposed as pull requests, tradeoffs discussed openly, issues prioritized by community feedback.

Visibility changed the nature of trust. Developers could see not just what shipped but why certain choices were made and others rejected. It also shifted the team’s priorities—instead of guessing, they could see exactly which issues developers cared about. The most effective open source projects make decision-making legible, so users and contributors understand how priorities are set.

A Necessary Break: Porting the Compiler to Go

TypeScript was long self-hosted: the compiler written in TypeScript, running as JavaScript. That enabled browser-based tooling and easy experimentation, but eventually hit a wall. JavaScript is single-threaded, lacks shared-memory concurrency, and has a flexible but expensive object model. The compiler was leaving enormous compute unused, and incremental optimization couldn’t bridge the gap.

The decision was to port to Go—controversial, but not a rewrite. The goal was semantic fidelity: the new compiler had to behave exactly like the old one, quirks and edge cases included. Rust, despite its popularity, would have required significant redesign because of ownership constraints and pervasive cyclic data structures. Go’s garbage collection and structural similarity preserved behavior while unlocking native execution and parallelism.

The result was substantial performance gains. The community didn’t have to relearn anything. Sometimes the responsible choice isn’t the most ambitious one—it preserves behavior, minimizes disruption, and removes a hard limit no amount of optimization can overcome.

In the AI Workflow, Grounding Beats Generation

Hejlsberg remains skeptical of AI-first languages. Models perform best on languages they’ve seen extensively, which favors mainstream ecosystems like JavaScript, Python, and TypeScript.

But AI changes what tooling must do. The traditional IDE assumed a developer writes code. Increasingly, AI generates code and developers supervise. In that world, deterministic tools like type checkers and refactoring engines aren’t creative aids—they’re guardrails. Their value is accuracy and constraint, exposing precise semantic information so AI systems can ask meaningful questions and get reliable answers.

The real risk isn’t bad code from AI; it’s plausible, confident code lacking grounding in the realities of a codebase. That shifts developer attention toward the tools that don’t generate code but constrain it: strong type systems, reliable refactors, accurate semantic models.

Institutional Memory Is Infrastructure

Hejlsberg remains optimistic about open collaboration despite its funding and maintenance challenges. A major reason is institutional memory. Years of discussion, decisions, and tradeoffs stay searchable and visible.

We have 12 years of history captured in our project. If someone remembers that a discussion happened, we can usually find it. The context doesn’t disappear into email or private systems.

For developers joining later, that context often matters as much as the code itself. Design debates, rejected ideas, and tradeoffs remain accessible long after individual decisions are made.

Patterns That Recur

Four decades in, the same themes hold:

  • Fast feedback loops matter more than elegance
  • Systems must accommodate imperfect code written by many people
  • Behavioral compatibility often outranks architectural purity
  • Visible tradeoffs build trust

These aren’t secondary concerns. They’re the fundamentals that determine whether a tool can adapt as its audience grows—and whether new ideas can take root without breaking what already works.