Back to Home

Anders Hejlsberg's Lessons: Software Architecture, TypeScript, C#

Learn the key principles of software design from Anders Hejlsberg, creator of C# and TypeScript: fast feedback, scaling, open-source, AI in development.

Anders Hejlsberg: Key Principles of Software Design and Lessons for Developers
Advertisement 728x90

Anders Hejlsberg's Principles: Lessons for Scalable and Enduring Software Architecture

Anders Hejlsberg, the architect behind iconic programming languages like C# and TypeScript, and the creator of Turbo Pascal and Delphi, has shaped software development approaches for decades. His career isn't just about building successful products; it's a continuous reflection on the principles that allow systems to withstand the tests of time and scale. A deep analysis of his work reveals universal patterns applicable to designing any complex system capable of long-term evolution. These lessons, forged through the creation and development of key tools for millions of developers, remain relevant in an ever-changing technological landscape, touching on aspects from feedback speed to the role of artificial intelligence and the importance of open collaboration.

1. Rapid Feedback — The Foundation of Productivity

Anders Hejlsberg's early experiences were shaped by severe constraints. In an era of computers with 64KB of memory, there was no room for abstractions that didn't justify themselves. He recalls that in such conditions, a developer could "hold everything in their head," and the key requirement was instant execution of code after writing it.

"When you typed code, you wanted to run it right away," — Anders Hejlsberg.

Google AdInline article slot

Turbo Pascal's impact wasn't so much about the Pascal language itself, but about radically shortening the feedback loop: edit, compile, run, debug, repeat — all happening without disk access and lengthy waits. This approach saved developers time and attention, allowing them to work more efficiently.

The same idea, albeit in a different form, found its embodiment decades later in TypeScript. The language itself is only part of its value. A significant portion of TypeScript's benefits lies in its powerful tooling: incremental type checking, rapid partial results, and language services that respond instantly even on very large codebases.

The practical takeaway here is crucial: developers can directly apply this principle when choosing tools. Fast feedback fundamentally changes behavior. When errors surface quickly, developers are more willing to experiment, more confident in refactoring, and find problems closer to when they arise. Conversely, when feedback is slow, teams are forced to compensate with complex conventions, workarounds, and convoluted processes. Whether choosing a language, framework, or internal tools, the speed of feedback is critical. Tools that shorten the distance between writing code and understanding its consequences earn trust. Those that add delay, even if powerful, often fall by the wayside.

Google AdInline article slot

2. Scaling Software Means Letting Go of Personal Preferences

When Hejlsberg transitioned from individual work to leading teams, particularly during the Delphi era, the most challenging aspect wasn't a technical change, but the need to relinquish personal preferences. He realized that in team development, "you have to accept that things aren't done the way you would prefer. Fixing it still won't change the behavior."

This approach applies far beyond language development. Any system that needs to scale across teams requires a shift from individual preferences to shared standards. The goal ceases to be "the code you would write" and becomes "code that many can understand, maintain, and evolve."

C# didn't emerge as an ideal "clean slate" concept but as a result of conflicting requirements. Visual Basic developers needed simplicity, C++ developers needed power, and Windows demanded pragmatism. The result wasn't a theoretically perfect system, but a language that people could effectively use. Programming languages succeed not because they are perfectly designed, but because they accommodate the real ways teams work and enable them to collaborate effectively.

Google AdInline article slot

3. Why TypeScript Extended JavaScript, Rather Than Replaced It

TypeScript emerged because JavaScript achieved a scale few languages ever could. As browsers became a true cross-platform runtime, teams began developing applications far exceeding the level effectively supported by dynamic typing. Early attempts to address this often were quite radical: some teams compiled other languages to JavaScript to gain access to static analysis and refactoring tools.

This approach never sat well with Hejlsberg. Telling developers to abandon an ecosystem they were already deeply invested in was unrealistic. Creating an entirely new language in 2012 would have required not just a compiler, but years of investment in editors, debuggers, refactoring tools, and, most importantly, community adoption.

Instead, TypeScript chose a different path — it extended JavaScript, inheriting its shortcomings while significantly simplifying large-scale project development. This wasn't an ideological decision but a purely practical one. TypeScript succeeded because it worked within the constraints developers already faced, rather than forcing them to abandon existing tools, libraries, and mental models.

Ultimately, the main lesson is the necessity of compromise. Improvements that accommodate existing workflows spread more easily, whereas enhancements requiring a complete replacement rarely gain traction. In practice, significant progress is often achieved by evolving the existing systems you already depend on, rather than attempting to start from scratch.

Openness and Adaptation to Change

4. Visibility is Key to Open-Source Success

TypeScript wasn't an overnight sensation. Early releases were formally open source, but development largely happened behind closed doors. This changed in 2014 when the project moved to GitHub, and the development process became fully open. Feature proposals came via pull requests, compromises were discussed publicly, and task priorities were determined based on community feedback.

This shift made the decision-making process transparent. Developers could see not only what was released, but also why certain decisions were made and others weren't. For the team, it also changed their approach to prioritizing work. Instead of guessing what was most important, they could directly observe the problems developers cared about.

Effective open-source projects do more than just publish code. They make the decision-making process visible — so that contributors understand priorities and trade-offs, which ultimately builds trust and fosters more active community participation.

5. Moving Away from JavaScript as the Implementation Language Was Necessary

For many years, the TypeScript compiler was self-hosting: written in TypeScript and running as JavaScript. This provided powerful in-browser tooling and simplified experimentation. However, limitations became apparent over time. JavaScript is single-threaded, lacks shared-memory concurrency, and its object model, while flexible, is resource-intensive. As TypeScript projects grew, the compiler left much of the available computing resources unused.

The team reached a point where further optimization wasn't enough. They needed a different execution model. The controversial decision was to port the compiler to Go. This wasn't a rewrite from scratch. The goal was semantic fidelity. The new compiler had to behave exactly like the old one, including quirks and edge cases. Rust, despite its popularity, would have required significant re-architecting due to ownership constraints and the pervasive use of cyclic data structures. Go's garbage collection and structural similarity to TypeScript allowed them to preserve behavior while enhancing performance and parallelism.

The result was a significant boost in performance, both in native execution and parallelism. More importantly, the community didn't have to relearn the compiler's behavior. Sometimes the most responsible choice isn't the most ambitious one, but the one that preserves behavior, minimizes disruption, and removes a hard constraint that no amount of incremental optimization can overcome.

The Future of Development and the Role of Collaboration

6. In the Age of AI, Constraints Matter More Than Generation

Anders Hejlsberg is skeptical of the idea of programming languages primarily designed for AI. He notes that large language models perform best with languages they have already widely encountered, which naturally favors massive ecosystems like JavaScript, Python, and TypeScript.

However, AI does change the game when it comes to tooling. The traditional IDE model assumed the developer writes code and uses tools to assist in the process. Increasingly, this relationship is reversing: AI systems generate code, and developers review and correct it. Deterministic tools like type checkers and refactoring engines serve as guardrails, preventing subtle errors. The value of such tools lies in precision and constraints: they must provide accurate semantic information so that AI systems can ask meaningful questions and receive reliable answers.

The risk isn't that AI systems will generate bad code, but that they will generate plausible code that doesn't account for all the nuances of a project's codebase. For developers, this shifts the focus. Ultimately, the most valuable tools in an AI-assisted workflow are those that properly constrain it. Strong type systems, robust refactoring tools, and accurate semantic models become indispensable enablers. They provide the structure that allows AI system outputs to be effectively checked, validated, and corrected, rather than blindly trusted.

7. The Critical Importance of Open Collaboration

Despite the challenges of funding and maintenance, Hejlsberg remains optimistic about open collaboration. One key reason is institutional memory. Years of discussions, decisions made, and compromises reached remain searchable and viewable.

This history isn't lost in private email chains or internal systems. It remains accessible to anyone who wants to understand how and why the system evolved. "We have 12 years of history recorded in our project," he explains. "If someone remembers that a discussion took place, we can usually find it. Context doesn't disappear into emails or private systems." This accessibility changes how systems evolve. Design discussions, rejected ideas, and compromises remain available long after individual decisions are made. For developers joining a project later, this shared context is often as valuable as the code itself.

Key Takeaways

  • Rapid feedback is a crucial factor for productivity and development quality, enabling experimentation and quick problem identification.
  • Scaling requires letting go of personal preferences in favor of shared, understandable rules and pragmatic solutions that meet real team needs.
  • Evolutionary development (extending existing systems, like TypeScript for JavaScript) is often more effective than revolutionary replacement, as it respects current workflows and ecosystems.
  • Process openness in open-source projects builds trust, ensures transparency in decision-making, and preserves valuable institutional memory.
  • When integrating AI into development, the focus should be on tools that provide precision and constraints (e.g., strong type systems), serving as "guardrails" for generated code.

Conclusion: A Model Repeated Over Decades

Across four decades of programming language development, the same themes consistently emerge:

  • Rapid feedback is more important than architectural elegance.
  • Systems must account for imperfect code written by many people.
  • Behavioral compatibility is often more critical than architectural purity and theoretical ideals.
  • Visible compromises and process transparency strengthen community trust.

These are not minor points. These are fundamental decisions that determine whether a tool can adapt as its audience grows and withstand the tests of the real world. Moreover, they serve as a foundation for innovation, ensuring that new ideas can be introduced without breaking what already works. For those building tools they want to see endure, these foundational principles are as important as any revolutionary features. And that, perhaps, is Anders Hejlsberg's most important lesson.

— Editorial Team

Advertisement 728x90

Read Next