7 learnings from Anders Hejlsberg: The architect behind C# and TypeScript

Published: (January 27, 2026 at 12:17 PM EST)
8 min read

Source: GitHub Blog

Anders Hejlsberg’s work has shaped how millions of developers code. Whether or not you recognize his name, you’ve likely touched his creations: he’s the creator of Turbo Pascal and Delphi, the lead architect of C#, and the designer of TypeScript.

We sat down with Hejlsberg to discuss his illustrious career and what it’s felt like to watch his innovations stand up to real‑world pressure. In a long‑form conversation, Hejlsberg reflects on:

  • What language design looks like once the initial excitement fades.
  • How performance limits surface and are addressed.
  • When open‑source becomes unavoidable.
  • How AI can impact a tool’s original function.

From this discussion emerges a set of patterns for building systems that survive contact with scale. Here’s what we learned:

Watch the full interview above.

Fast Feedback Matters More Than Almost Anything Else

Anders Hejlsberg’s early instincts were shaped by extreme constraints. In the era of 64 KB machines, there was no room for abstraction that didn’t pull its weight.

“You could keep it all in your head,” he recalls.
“When you typed your code, you wanted to run it immediately.”

The Turbo Pascal lesson

Turbo Pascal’s impact didn’t come from the Pascal language itself; it came from shortening the feedback loop:

  1. Edit
  2. Compile
  3. Run
  4. Fail
  5. Repeat

All of this happened without touching the disk or waiting for tooling to catch up. That tight loop respected developers’ time and attention.

The same idea in TypeScript

Decades later the principle re‑appears in TypeScript, albeit in a different form. The language is only part of the story; most of its value comes from its tooling:

  • Incremental checking – only the changed parts are re‑analyzed.
  • Fast partial results – you get diagnostics as you type.
  • Responsive language services – IntelliSense, refactorings, and navigation work instantly even on large codebases.

Why fast feedback matters

  • Rapid experimentation – developers try ideas without fear of long wait times.
  • Confident refactoring – errors surface immediately, so changes can be made safely.
  • Early bug detection – problems are caught close to the moment they’re introduced.

When feedback is slow, teams compensate with:

  • Rigid conventions
  • Work‑arounds
  • Additional process overhead

Takeaway

Whether you’re choosing a language, framework, or internal tooling, responsiveness matters. Tools that shrink the distance between writing code and understanding its consequences earn trust and adoption. Powerful tools that introduce latency, however, often end up on the sidelines.

Scaling Software Means Letting Go of Personal Preferences

As Anders Hejlsberg moved from largely working alone to leading teams—particularly during the Delphi years—the hardest adjustment 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.”
Anders Hejlsberg

That mindset applies well beyond language design. Any system that needs to scale across teams requires a shift from personal taste to shared outcomes.

  • The goal stops being code that looks the way you would write it.
  • It becomes code that many people can understand, maintain, and evolve together.

C# did not emerge from a clean‑slate ideal. It emerged from conflicting demands:

StakeholderDesired Quality
Visual Basic developersApproachability
C++ developersPower
Windows platformPragmatism

The result was not theoretical purity. It was a language that enough people could use effectively.

Languages do not succeed because they are perfectly designed.
They succeed because they accommodate the way teams actually work.

Why TypeScript Extended JavaScript Instead of Replacing It

TypeScript exists because JavaScript achieved a scale few languages ever reach. As browsers became the de‑facto cross‑platform runtime, teams began building applications far larger than dynamic typing comfortably supports.

Early attempts to cope were often extreme. Some teams compiled other languages into JavaScript just to get access to static analysis and refactoring tools—a strategy that never sat well with Anders Hejlsberg.

The Practical Reality

  • Ecosystem lock‑in: Asking developers to abandon the JavaScript ecosystem was unrealistic.
  • Tooling gap: A brand‑new language in 2012 would have required not only a compiler but also years of investment in editors, debuggers, refactoring tools, and community adoption.

TypeScript’s Chosen Path

Instead of starting from scratch, TypeScript extended JavaScript in place, inheriting its quirks while making large‑scale development more tractable. This decision was driven by practicality, not ideology.

Key Takeaways

  1. Respect existing workflows. Improvements that fit into current tools, libraries, and mental models spread quickly.
  2. Compromise wins. Meaningful progress often comes from making the systems you already depend on more capable, rather than trying to replace them wholesale.

The broader lesson is clear: incremental, compatible enhancements tend to succeed where radical replacements falter.

Visibility Is a Key Ingredient of Successful Open‑Source Projects

The early days of TypeScript

  • The first releases were nominally open source, but most development happened behind closed doors.

The 2014 turning point

  • The project moved to GitHub and adopted a fully public development process.
  • Features were proposed via pull requests.
  • Trade‑offs were discussed openly.
  • Issues were prioritized based on community feedback.

What changed?

Before (closed)After (open)
Decisions were opaqueDecision‑making became visible
Developers guessed prioritiesPriorities were evident from the issue tracker
Limited community insightCommunity could see what shipped and why

Why visibility matters

  • Transparency helps contributors understand the rationale behind each choice.
  • Prioritization aligns with the real needs of users and developers.
  • Trust builds a stronger, more engaged community.

Takeaway

The most effective open‑source projects do more than just share code—they make decision‑making visible, allowing contributors and users to see how priorities are set and why trade‑offs are made. This transparency fuels collaboration, accelerates development, and sustains the project over the long term.

Leaving JavaScript as an Implementation Language Was a Necessary Break

For many years, TypeScript was self‑hosted: the compiler was written in TypeScript and ran as JavaScript. This enabled powerful browser‑based tooling and made experimentation easy.

Why JavaScript Became a Limiting Factor

  • Single‑threaded execution – no native shared‑memory concurrency.
  • Flexible but expensive object model.
  • As TypeScript projects grew, the compiler left a large amount of available compute unused.

The team eventually realized that further micro‑optimisations would not be enough; a different execution model was required.

The Decision to Port the Compiler to Go

  • Not a rewrite – the goal was semantic fidelity: the new compiler had to behave exactly like the old one, quirks and all.
  • Rust was attractive, but its ownership model would have forced a major redesign because the compiler relies heavily on cyclic data structures.
  • Go offered garbage collection and a structural similarity to JavaScript that made it possible to preserve behavior while unlocking performance and concurrency.

Outcomes

  • Substantial performance gains from native execution and parallelism.
  • Minimal disruption for the community – developers did not need to relearn the compiler’s behavior.

Sometimes the most responsible choice isn’t the most ambitious one; it’s the one that preserves behavior, minimizes disruption, and removes a hard limit that no amount of incremental optimization can overcome.

In an AI‑Driven Workflow, Grounding Matters More Than Generation

Hejlberg is skeptical of the idea of AI‑first programming languages. Models excel at languages they have already seen extensively, which naturally favors mainstream ecosystems like JavaScript, Python, and TypeScript.

The Changing Role of Tooling

The traditional IDE model assumes a developer writes code and uses tools for assistance along the way.
Increasingly, that relationship is reversing:

  1. AI systems generate code.
  2. Developers supervise and correct it.
  3. Deterministic tools (type checkers, refactoring engines) provide guardrails that prevent subtle errors.

In this new paradigm, the value of tooling is not creativity; it is accuracy and constraint. Tools must expose precise semantic information so that AI systems can ask meaningful questions and receive reliable answers.

Why Grounding Is Critical

The risk isn’t that AI will generate bad code; it’s that it will generate plausible, confident code that lacks sufficient grounding in the realities of a codebase. Without solid constraints, such code can:

  • Appear correct at a glance but break hidden invariants.
  • Introduce subtle bugs that are hard to trace.
  • Misalign with project‑specific conventions and architecture.

Where Developers Should Focus Their Attention

The most valuable tools in an AI‑assisted workflow are not the ones that generate the most code, but the ones that constrain it correctly:

  • Strong type systems – catch mismatches early and provide clear contracts.
  • Reliable refactoring tools – ensure structural changes remain consistent.
  • Accurate semantic models – give AI a precise understanding of the codebase’s intent and constraints.

These guardrails provide the structure that allows AI output to be reviewed, validated, and corrected efficiently, rather than being trusted blindly.

Why Open Collaboration Is Critical

Despite the challenges of funding and maintenance, Hejlsberg remains optimistic about open collaboration. A key reason is institutional memory—the ability to keep years of discussions, decisions, and trade‑offs searchable and visible.

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

Benefits of Preserving History

  • Transparency: The evolution of a system stays visible to anyone who wants to understand the “how” and “why.”
  • Continuity: New developers can quickly get up to speed by reading past design debates, rejected ideas, and trade‑offs.
  • Better Decision‑Making: Having access to prior context helps avoid repeating mistakes and informs future choices.

This visibility changes how systems evolve. Design debates, rejected ideas, and trade‑offs remain accessible long after individual decisions are made, and for developers joining a project later, that shared context often matters as much as the code itself.

A pattern that repeats across decades

Across four decades of language design, the same themes recur:

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

These aren’t secondary concerns. They’re fundamental decisions that determine whether a tool can adapt as its audience grows. Moreover, they ground innovation by ensuring new ideas can take root without breaking what already works.

For anyone building tools they want to see endure, those fundamentals matter as much as any breakthrough feature. And that may be the most important lesson of all.

Did you know TypeScript was the top language used in 2025?
Read more in the Octoverse report →


Written by

Aaron Winston

Aaron helps lead content strategy at GitHub with a focus on everything developers need to know to stay ahead of what’s next. He still likes the em dash despite its newfound bad rap.

Back to Blog

Related posts

Read more »

This Year in LLVM (2025)

Article URL: https://www.npopov.com/2026/01/31/This-year-in-LLVM-2025.html Comments URL: https://news.ycombinator.com/item?id=46841187 Points: 17 Comments: 0...

Methods and Parameter Usage in C#

Defining and Calling Methods csharp static void Greet { Console.WriteLine'Hello!'; } static void Main { Greet; // method call } text // Output: Hello! Methods...