Creator of TypeScript: 10x Faster Typescript, Why AI Won't Replace SWEs | Anders Hejlsberg

Creator of TypeScript: 10x Faster Typescript, Why AI Won't Replace SWEs | Anders Hejlsberg

Host
Ryan Peterman
Guests
Anders Hejlsberg

Executive Summary

Ryan Peterman interviews Anders Hejlsberg about TypeScript's origins, the native rewrite of its compiler, programming-language design, and software engineering in the age of AI. Hejlsberg explains that TypeScript began in JavaScript because self-hosting kept the project inside its target ecosystem and enabled broad tooling and platform reach. He describes the native rewrite as a performance and scalability project, with shared-memory concurrency and multi-core utilization as important motivations. The team chose to port the existing compiler to preserve semantics and compatibility rather than start over. The conversation closes with a cautious view of AI-assisted programming: agents can write substantial amounts of code, but engineers still need to understand, review, and take responsibility for the result.

Chapters & Key Takeaways

Hejlsberg describes self-hosting in the JavaScript ecosystem as an early strategic advantage for TypeScript.
The native compiler rewrite is presented as a response to compute performance, scalability, and concurrency constraints.
The rewrite was a port intended to preserve existing semantics and backwards-compatible behavior.
TypeScript's type system is described as primarily serving developer tooling rather than changing runtime behavior.
Hejlsberg rejects the idea that AI-generated code removes the need for engineers to understand and review the work.
The interview frames software engineering as shifting toward supervising and reviewing agent-produced code while retaining human responsibility.

Why TypeScript Needed a Native Rewrite, and What AI Programming Changes

Why TypeScript Started in JavaScript

Anders Hejlsberg explains that TypeScript began inside the JavaScript ecosystem because self-hosting made the team daily users of the language and its tools. That feedback made failures visible quickly, while JavaScript's reach meant the compiler could run across platforms, including the browser.

The Type Checker Serves Developers

In Hejlsberg's account, TypeScript is unusual because its types do not change runtime behavior. They primarily support developer tools such as completion, refactoring, and code navigation, while the gradual type system allows typed and untyped code to coexist.

Performance and Concurrency First

Hejlsberg presents the native rewrite as a response to performance and scalability. JavaScript imposed a compute penalty for compiler workloads and limited shared-memory concurrency, leaving modern multi-core processors underused.

Choosing Go Under Constraints

The language choice was described as a structured engineering decision. The replacement had to provide native performance and access to shared-memory concurrency while remaining practical for a compiler that had accumulated substantial behavior and compatibility expectations.

Compatibility Over Reinvention

The rewrite was approached as a port rather than an opportunity to invent a new TypeScript. Preserving the existing compiler's semantics and behavior mattered because users and tools depend on the language as it already works.

AI and Incumbent Languages

Hejlsberg argues that AI is strongest with languages represented heavily in its training data, including JavaScript, TypeScript, and Python. He also says static validation can let an agent find some mistakes before presenting code, though he describes this as an advantage rather than a guarantee.

Human Responsibility Remains

The closing argument is not that AI makes engineering disappear. Hejlsberg says someone still needs to understand what the generated code is doing, how it relates to the business problem, and whether it is relevant to the organization. The tools may change how code is produced, but responsibility for understanding and reviewing the result remains human. Continue at 61:33

Interview Highlights9 exchanges

Direct dialogue & timestamps from the recording

QRyan Peterman
1:15

Why was the TypeScript compiler originally written in JavaScript?

AAnders Hejlsberg

No, it's a good question. Honestly, if you had told me before the TypeScript project started, "Anders, you're going to be writing compilers in JavaScript," I'd have said no. The original prototypes for TypeScript — the Strata project, as it was called in the very early days — were actually written in C, as an adaptation of the JavaScript parser we had in IE, and then we moved to JavaScript but wrote it sort of C-style. Why did we go with JavaScript? If you can self-host in the ecosystem that you want to be a part of, that is dramatically better than putting yourself outside the ecosystem and trying to target it. By writing it in TypeScript, we were daily users of TypeScript and of the tooling we were building; whenever something didn't work right or didn't perform, we knew it immediately. In the early years that was a huge boon. JavaScript also runs everywhere, so our compiler could automatically run on every platform, even in the browser — a native-code solution at that time couldn't have run in the browser, and WebAssembly didn't exist yet. And people didn't really realize how fast JavaScript had gotten: Google's work with V8 brought it within two to 3x of native code, which is pretty darn impressive. It was fully possible to write performant compilers in JavaScript, because often it's the algorithms that determine how performant you are, not necessarily the runtime environment.

QRyan Peterman
3:39

Is there anything unique about the TypeScript compiler?

AAnders Hejlsberg

I think there are a couple of things that are pretty unique about TypeScript's compiler. First of all, it doesn't target machine code — it targets JavaScript; some people call that a transpiler, and in a sense the compilation phase is mostly about removing the type annotations and turning your TypeScript back into JavaScript. In the early days an important part of the compilation process was also to downlevel your JavaScript, because the runtime environments at the time were not evergreen — some lagged multiple years behind the standard. When classes got standardized, most JavaScript runtimes didn't implement them, but it turns out you can downlevel to constructor functions and transform the code. And then of course the type checking is the big thing. The type checker in TypeScript is quite unlike any other type checker in other compilers: typically type checkers exist to guide the code generator, but since we erase the types, the types have no impact whatsoever on the runtime behavior of the code. They purely exist for tooling sake and for the developer sake, to guide things like statement completion, refactoring, and code navigation. TypeScript also has a gradual type system: you can have half of your code typed and the other half is just any, and very few languages have anything like that. That actually made it fascinating to work on, because we were solving problems that no one had solved before.

QRyan Peterman
7:29

So with the the native rewrite of this originally fully JavaScript compiler, what was the problem you were trying to solve with the rewrite and why did you end up write rewriting it in native code?

AAnders Hejlsberg

The problem we were trying to solve is real simple: performance and scalability. JavaScript was never really optimized for compute-intensive workloads like compilers — it's more about creating UI that runs in a browser. In JavaScript, first of all, you pay a 2 to 3x performance penalty compared to native code; it depends on the workload, but for compute that's about where it's at. And secondly there are a lot of restrictions around use of concurrency. JavaScript was always engineered to be a single-threaded language — that's why we have callbacks and async, because you can't spin up threads. That's mostly a good thing, because concurrency in a language with mutable data is very hard: you can have races and deadlocks and all of that. Functional programming languages are easier with concurrency because all the data is immutable. JavaScript doesn't give you access to concurrency other than web workers, and web workers can't share data between each other other than by remoting it — one worker has to turn data into JSON to hand it to another. In other words, you can't have shared-memory concurrency, and really that's what we wanted in order to gain the performance we were leaving on the table by not utilizing the multi-core CPUs everyone has today. Moore's law has stopped giving us faster CPUs; it's giving us more CPUs, and we were leaving money on the table in multiple ways. So we looked for a language that would get us out of both of those binds: it had to be native, and it had to have access to shared-memory concurrency.