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
HostRyan Peterman
GuestsAnders 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

6 takeaways
  1. Hejlsberg describes self-hosting in the JavaScript ecosystem as an early strategic advantage for TypeScript.

  2. The native compiler rewrite is presented as a response to compute performance, scalability, and concurrency constraints.

  3. The rewrite was a port intended to preserve existing semantics and backwards-compatible behavior.

  4. TypeScript's type system is described as primarily serving developer tooling rather than changing runtime behavior.

  5. Hejlsberg rejects the idea that AI-generated code removes the need for engineers to understand and review the work.

  6. The interview frames software engineering as shifting toward supervising and reviewing agent-produced code while retaining human responsibility.

Deep Read

Long-form read

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

Anders Hejlsberg explains that TypeScript began inside the JavaScript ecosystem because self-hosting made the team daily users of the language and its tools.

Read the full article

Interview Highlights

9 exchanges
  • Q

    Why was the TypeScript compiler originally written in JavaScript?

    Ryan Peterman asked01:15
    A
    Anders Hejlsberg answered

    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.

  • Q

    Is there anything unique about the TypeScript compiler?

    Ryan Peterman asked03:39
    A
    Anders Hejlsberg answered

    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.

  • Q

    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?

    Ryan Peterman asked07:29
    A
    Anders Hejlsberg answered

    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.