Why a port instead of a rewrite? What's the difference? #410
Replies: 3 comments 3 replies
-
One of the things thats been mentioned before in the community rewrites is that Typescript has no working working specs/standard. It makes rewriting in community harder. With typescript now being ported to go ("native"). Can we start saying a language spec / standard rather than just a huge implementation? I know its a port but maybe a language spec/standard a good idea |
Beta Was this translation helpful? Give feedback.
-
One very curious question; how are you creating the port? Does it involve heavy use of LLMs? I guess this could be something they are great at! |
Beta Was this translation helpful? Give feedback.
-
This is good explanation. On first read I still wasn't buying fear of breaking changes was a valid reason, but on further reads I could see it was actually the scale at which existing project could be impacted that's the main concern here. A complete rewrite could mean years before release then even more years before the community fully adopt the change. I guess it's not a perfect situation, but reality never was. |
Beta Was this translation helpful? Give feedback.
-
Broadly speaking, there are two possible strategies you can take when changing languages:
Porting is faster to execute, but requires that the new language be at least somewhat architecturally compatible with the original language. Porting also tends to bring over any existing bugs or quirks of the original codebase. Rewriting is more fun, and can be done in any language, but takes a lot longer. Rewriting introduces a new set of bugs, quirks, and different trade-offs.
Which to choose? Which of these pros and cons is most relevant?
The primary constraint here relates to compatibility. Something we're keenly aware of is that TypeScript exemplifies Hyrum's Law: seemingly without exception, every single optimization, behavior, design limitation, bug, or just quirk of TypeScript is (intentionally or otherwise) relied on by some project or another. In a type system as complex as TypeScript's, type inference can often have multiple correct results to choose from, and subtle changes can end up breaking code unintentionally that took a dependency on very particular details of our implementation.
We also know that people are keen to exercise any new capability in the type system to create more expressive types. Many times we'll fix a design limitation, and this quickly results in new type constructs that are adopted in popular libraries. Once we create these new spaces of expressiveness, they're immediately occupied and become critical parts of the language. Likewise, many optimizations exist which are effectively mandatory in any implementation in order to typecheck projects in a reasonable amount of time.
The prospect of a ground-up rewrite thus presents two large challenges. Replicating ~100 engineer-years of effort from scratch is going to take a very long time, even with the benefits of hindsight. While everyone loves writing in a brand-new codebase with no design constraints, starting over from scratch would take multiple years before we could produce anything plausibly useful. Worse, even if we did that, a brand new system would have a completely disjoint set of new optimizations, limitations, and bugs. This would make it so incompatible in practice as to likely be unusable by most projects which have any meaningful type complexity (which is actually all of them, due to dependencies on the complex types used to represent popular libraries).
For a new native TypeScript to be useful, it needs to be not just compatible with existing TypeScript syntax and configuration, but compatible to the highest possible fidelity in every regard. This straightforwardly implies something like a line-for-line port, rather than a fresh codebase written from scratch. As long as the checker builds up the same semantic primitives, it'll produce the same results, with the same algorithmic complexity, no matter the implementation language. We've set up the groundwork to do this, and the port at this point is largely a mechanical effort, progressing very quickly.
Another big upside to this approach is that we expect to easily apply bug fixes to both codebases with little overhead. This will be an important factor during the transition period where we want user feedback on the new codebase, but need to keep maintaining the current codebase with fixes and new features.
Beta Was this translation helpful? Give feedback.
All reactions