Why Go? #411
Replies: 112 comments 268 replies
-
I'd appreciate a much more in-depth write-up on this technical decision. The choice of Go is quite surprising given that Microsoft makes C#, an obvious competitor to Go, which has bootstrapped its own compiler to great success. And of course, Microsoft has many customers that use both TS and C#. This seems like an unfortunate missed opportunity to unify Microsoft's web development story and do something greater. (In fact, this comes off as a bit of a vote of no confidence in C#, given that Anders is the original creator of C# and his team has now chosen not to use it. Seems that if there were issues with C#, the better move would be to work with the C# team to address those, making C# the best language for the new TS compiler. I'm just not sure how to interpret this move...) If not C#, I would have expected Rust, since that's where the rest of the ecosystem is. So, another surprise there. Additionally, both C# and Rust have strong support for WASM. In my understanding, much better than Go. A non-trivial set of folks need to run the TS compiler in-browser, so I'm not sure how this decision is going to affect those scenarios. I'm glad performance is taking priority but confused (and a little disappointed) by the specifics. Edit: See my follow-up post for my take on how this decision was likely made. |
Beta Was this translation helpful? Give feedback.
This comment was marked as off-topic.
This comment was marked as off-topic.
-
Actually, I don't think tsc would make much use of Go's complex standard libraries like networking anyway. Then maybe, tsc-go can be compiled using gccgo or tinygo(LLVM based). The WASM and other corner usage can still find a way. |
Beta Was this translation helpful? Give feedback.
-
Not beating the "Microsoft doesn't dogfood their own products" allegations |
Beta Was this translation helpful? Give feedback.
-
Excellent writeup. I'd also love to read more about the various prototypes/evaluations that went into picking go, it sounds like a fascinating journey. I'd be especially curious to hear about plans for the mitigation of go's wasm/js interop limitations. Also whether you expect to be able to leverage parallelism, or if maintaining a deep similarity between the go and TS codebases makes that difficult. Incredibly excited for this! |
Beta Was this translation helpful? Give feedback.
-
Switch to Rust while it's not too late. |
Beta Was this translation helpful? Give feedback.
-
It's time to give up on .NET. Even Microsoft has chosen Go for critical components like dapr framework and the TS compiler. Microsoft itself has abandoned its own product first. |
Beta Was this translation helpful? Give feedback.
-
Things like this make me ashamed to even build my career on C# .NET. Microsoft doesn't use C# on any of their high impact, serious projects like Azure, Bing, Dapr, VS Code, Typescript etc. They overwhelmingly use tools outside of .NET ecosystem like Java, React, Go etc. If they don't use their own tools in their flagship products, I have no confidence in their tools and it just signals the developer community that instead of focusing on learning, using and growing .NET, they should just focus their energy on learning Java, React, Go etc. This attitude of Microsoft really hurts .NET community because for someone new to software development if they see Microsoft treating their own tools like second class citizens, they'll have no drive to learn .NET. And when more people do this over time, C# community will be pretty much gone. Thanks Microsoft. I'll do my best to move my org away from C#/ Azure to Java, Go/ AWS etc. Reference: |
Beta Was this translation helpful? Give feedback.
-
Who is going to vibe-code it in a week? |
Beta Was this translation helpful? Give feedback.
-
What is missing from OP's statement is that there is still no technical justification to use Go. > Go also offers excellent control of memory layout and allocation (both on an object and field level) without requiring that the entire codebase continually concern itself with memory management. If the concern with migrating from a JavaScript runtime was avoiding manually managing memory then it's a weak argument since there have been many close comparisons of I/O-bound tasks between Node and Go that implied a minimal difference—which is relevant since the actual gains in using Go is only when there is a plausible use case for concurrency. For the record, there are many patterns in non-GC'd statically-typed compiled PLs e.g. pooled allocators that are barely challenging to use internally, i.e. in the case where there are upfront allocations. > In non-batch scenarios, most of our up-front allocations (ASTs, etc.) live for the entire life of the program... When the data is upfront, it is more reasonable to use allocation strategies that fit the task e.g. fixed-size or growable where it makes sense. It is also easier to cache and vectorize some procedures e.g. tokenization, but my assumption is that Even when it is not feasible for a complete rewrite, it is more reasonable to use Rust/C++17^. |
Beta Was this translation helpful? Give feedback.
-
Operating Systems (OS) that performed better than Linux and Windows were written in C# (Midori), and also one of the best compilers (Roslyn) in the industry is written in C#. So, I do not see the reason not to use C#, other than you were porting instead of rewriting. Well done to you and your team |
Beta Was this translation helpful? Give feedback.
-
Can't wait when C# compiler will be rewritten in go! |
Beta Was this translation helpful? Give feedback.
-
i too am butt hurt that a devtool that has nothing directly to do with C# hasn't been written in C# |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
At the end of the day, the focus is on boosting performance and enhancing the DX across codebases, even if some community members might have preferred Rust or another language. It’s a reminder that the right tool for the job is often the one that offers the best overall trade-offs for the project’s needs and the team's expertise. I trust these people to make informed decisions and support them going forward with the rewrite in Go despite not being a fan of Go at all and much preferring Rust. To me, it doesn't make a difference if it's built in Go, Rust, C++, F#, Brainfuck or ADA: at the close of play, I still get the benefits of faster TypeScript tooling regardless of the hidden intrincacies. |
Beta Was this translation helpful? Give feedback.
-
This choice would've surprised me too... more than a decade ago. But I already depleted my surprise a long time ago, seeing a Microsoft Build and watching in shock as all Microsoft developers used Macs on stage while doing their presentations about the Microsoft developer languages and ecosystem. Since then I personally have little expectations... A win for programming diversity! Why use your own tools when you can create unneeded external dependencies? |
Beta Was this translation helpful? Give feedback.
-
Let's write Go in Rust ahahha |
Beta Was this translation helpful? Give feedback.
-
language choice is just a smoke bomb concealing their reluctance to refactoring the codebase, and yeah, I feel you C# users. |
Beta Was this translation helpful? Give feedback.
-
I am pretty sure whichever language they had used under the hood would have butt hurt the community's feelings as always, but it's a big win for Go lang |
Beta Was this translation helpful? Give feedback.
-
This is a huge loss for C#, the differences are so laughably small for a language you can CONTROL vrs one you can't. The optics of this are tragic. This was not a smart choice and will have repercussions much greater than typescript. This was a mistake. |
Beta Was this translation helpful? Give feedback.
-
(Adding my comment again since the original one was a reply to a reply and gets swallowed by thread truncation...) Our decision to port to Go underscores our commitment to pragmatic engineering choices. Our focus was on achieving the best possible result regardless of the language used. At Microsoft, we leverage multiple programming languages including C#, Go, Java, Rust, C++, TypeScript, and others, each chosen carefully based on technical suitability and team productivity. In fact, C# still happens to be the most popular language internally, by far. The TypeScript compiler's move to Go was influenced by specific technical requirements, such as the need for structural compatibility with the existing JavaScript-based codebase, ease of memory management, and the ability to handle complex graph processing efficiently. After evaluating numerous languages and making multiple prototypes — including in C# — Go emerged as the optimal choice, providing excellent ergonomics for tree traversal, ease of memory allocation, and a code structure that closely mirrors the existing compiler, enabling easier maintenance and compatibility. In a green field, this would have been a totally different conversation. But this was not a green field - it's a port of an existing codebase with 100 man-years of investment. Yes, we could have redesigned the compiler in C# from scratch, and it would have worked. In fact, C#'s own compiler, Roslyn, is written in C# and bootstraps itself. But this wasn't a compiler redesign, and the TypeScript to Go move was far more automatable and more one-to-one in its mapping. Our existing codebase is all functions and data structures - no classes. Idiomatic Go looked just like our existing codebase so the port was greatly simplified. While this decision was well-suited to TypeScript’s specific situation, it does not diminish our deep and ongoing investment in C# and .NET. A majority of Microsoft's services and products rely heavily on C# and .NET due to their unmatched productivity, robust ecosystem, and strong scalability. C# excels in scenarios demanding rapid, maintainable, and scalable development, powering critical systems and numerous internal and external Microsoft solutions. Modern, cross-platform .NET also offers outstanding performance, making it ideal for building cloud services that run seamlessly on any operating system and across multiple cloud providers. Recent performance improvements in .NET 9 further demonstrate our ongoing investment in this powerful ecosystem (https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-9/). Let's be real. Microsoft using Go to write a compiler for TypeScript wouldn't have been possible or conceivable in years past. However, over the last few decades, we've seen Microsoft's strong and ongoing commitment to open-source software, prioritizing developer productivity and community collaboration above all. Our goal is to empower developers with the best tools available, unencumbered by internal politics or narrow constraints. This freedom to choose the right tool for each specific job ultimately benefits the entire developer community, driving innovation, efficiency, and improved outcomes. And you can't argue with a 10x outcome! No single language is perfect for every task, and at Microsoft, we celebrate the strength that comes from diversity in programming languages. Our commitment to C# and .NET remains stronger than ever, continually enhancing these technologies to provide developers with the tools they need to succeed now and into the future. |
Beta Was this translation helpful? Give feedback.
-
How does TypeScript currently work in my local React (Next.js/Vite) setup?
What changes for developers using TypeScript locally?
Will TypeScript still depend on Node.js and V8?
|
Beta Was this translation helpful? Give feedback.
-
I suppose I shouldn't be surprised that well-reasoned post that more-or-less boils down to "you'd understand if you worked on the project" has a lot of angry opinions from people who do not work on the project. I think it's a testament to how much Microsoft's culture has improved over the last decade that the developers on one of their biggest projects are able to pick the tool they think is the best fit for the job, instead of being forced to pick the Microsoft tool because it's the Microsoft tool. |
Beta Was this translation helpful? Give feedback.
-
臣等正欲死战,陛下何故先降? |
Beta Was this translation helpful? Give feedback.
-
Opinions and debates on language is what devs do the best. |
Beta Was this translation helpful? Give feedback.
-
I was learning Rustlang:/ the next step will be Golang:) |
Beta Was this translation helpful? Give feedback.
-
I like the pragmatism of choosing Go. It's not a rewrite, it's a port. The thing that I don't like in Go is that (I've read this a few years ago, so this might not be the current reality) was created by some folks that also created Unix, Inferno, and Plan9, so the whole part that interact with the OS (file system, time, ...) is very Unixy and don't play well on Windows. |
Beta Was this translation helpful? Give feedback.
-
I'm going to lock this (for a while) as comments are getting a bit circular, the most salient points have been addressed, and there are a lot of incoming links to this page that aren't loading correctly for folks because the thread is too long. We really appreciate the input and hope that we've provided clarity on this one. |
Beta Was this translation helpful? Give feedback.
-
Language choice is always a hot topic! We extensively evaluated many language options, both recently and in prior investigations. We also considered hybrid approaches where certain components could be written in a native language, while keeping core typechecking algorithms in JavaScript. We wrote multiple prototypes experimenting with different data representations in different languages, and did deep investigations into the approaches used by existing native TypeScript parsers like swc, oxc, and esbuild. To be clear, many languages would be suitable in a ground-up rewrite situation. Go did the best when considering multiple criteria that are particular to this situation, and it's worth explaining a few of them.
By far the most important aspect is that we need to keep the new codebase as compatible as possible, both in terms of semantics and in terms of code structure. We expect to maintain both codebases for quite some time going forward. Languages that allow for a structurally similar codebase offer a significant boon for anyone making code changes because we can easily port changes between the two codebases. In contrast, languages that require fundamental rethinking of memory management, mutation, data structuring, polymorphism, laziness, etc., might be a better fit for a ground-up rewrite, but we're undertaking this more as a port that maintains the existing behavior and critical optimizations we've built into the language. Idiomatic Go strongly resembles the existing coding patterns of the TypeScript codebase, which makes this porting effort much more tractable.
Go also offers excellent control of memory layout and allocation (both on an object and field level) without requiring that the entire codebase continually concern itself with memory management. While this implies a garbage collector, the downsides of a GC aren't particularly salient in our codebase. We don't have any strong latency constraints that would suffer from GC pauses/slowdowns. Batch compilations can effectively forego garbage collection entirely, since the process terminates at the end. In non-batch scenarios, most of our up-front allocations (ASTs, etc.) live for the entire life of the program, and we have strong domain information about when "logical" times to run the GC will be. Go's model therefore nets us a very big win in reducing codebase complexity, while paying very little actual runtime cost for garbage collection.
We also have an unusually large amount of graph processing, specifically traversing trees in both upward and downward walks involving polymorphic nodes. Go does an excellent job of making this ergonomic, especially in the context of needing to resemble the JavaScript version of the code.
Acknowledging some weak spots, Go's in-proc JS interop story is not as good as some of its alternatives. We have upcoming plans to mitigate this, and are committed to offering a performant and ergonomic JS API. We've been constrained in certain possible optimizations due to the current API model where consumers can access (or worse, modify) practically anything, and want to ensure that the new codebase keeps the door open for more freedom to change internal representations without having to worry about breaking all API users. Moving to a more intentional API design that also takes interop into account will let us move the ecosystem forward while still delivering these huge performance wins.
Beta Was this translation helpful? Give feedback.
All reactions