Adopting TypeScript at bet365

We at bet365 have always had a strong relationship with flash — it has powered all of our In-Play apps since their conception, as well as our whole desktop website. Sadly, though, it wasn’t to be and even in the best relationships there comes a time when you just need to move on.

So at the beginning of 2013, we were looking at moving the front-end architecture from our fully real-time flash site over to a new, future proof JavaScript framework more suited to the modern web.

Naturally, we wanted the same robust development pipeline available to us in flash for our new JavaScript based solution. We wanted our developers to feel just as comfortable developing with JavaScript and the DOM as they did making the same experiences in the flash display list.

However, it was also just as important not to alienate developers currently working on the mobile/tablet front-end who were more from an ASP.NET background. For these reasons, Microsoft’s Visual Studio quickly singled itself out as a strong potential IDE candidate due to its familiar and powerful IntelliSense capabilities available when authoring JavaScript.

On the subject of JavaScript authoring, we had already started a few different proof-of-concept pieces using a Transpiler language, like CoffeeScript and Microsoft’s TypeScript. Ultimately, these pieces led us to believe that the adoption of TypeScript, with its familiar syntax and strong resemblance to the outputted JavaScript code, was the right thing to do.

TypeScript, for those of you who are unfamiliar, is a strict superset of JavaScript developed by Microsoft which provides a compile-time type-checking system similar to what you’ll find in strongly typed languages such as C#, Java and AS3.

Unfortunately, at the time, the language was still in its infancy and there were uncertainties around the level of support it would receive from Microsoft. The decision was made to postpone adoption until the language itself had reached the big 1.0.

Decision Time

It wasn’t until 18 months after going live with our new JavaScript framework that we were in a position to re-evaluate what was then version 1.4 of TypeScript. There were a number of factors to consider; was TypeScript still the best choice? What problems were we trying to solve by migrating? How would we even approach converting the now roughly 40,000 lines (and growing) of existing JavaScript over to the new language?

As it turned out, TypeScript still fit our needs as a large development team and having had the opportunity to have worked with what was now turning into a large Raw JS codebase, we were starting to miss some of the benefits from more strongly-typed languages we’d used in the past, such as AS3 and the ASP.NET family of languages.

This was all fresh code. This was all code that had been subject to a pretty tight new set of authoring standards. A single class per file, logically namespaced, with well-defined naming schemes and all heavily documented using the VSDOC comment syntax, including type information for reference. Yet still, the bigger the codebase got, the harder it became to maintain and take the continuous improvement approach to our code as we had become accustomed to in the past.

It was decided to see if a script could be written that simply converted the *.js classes into *.ts classes. As the codebase had been written using the same prototypal inheritance model as TypeScript, and the coding standards we had adopted at the start of development covered a lot of TS’s language constructs via inference (access modifiers, types), we had the finalised script after just a few days.

The script, which was written in TypeScript, managed about 85% of the conversion process. It covered:

  • Namespaces
  • Classes
  • Inheritance
  • Import statements
  • Conversion of comments from VSDOC to JSDOC
  • Class member properties with type definitions
  • Static properties with type definitions
  • Method signatures with type definitions for parameters and return types
  • Public & private access modifiers inferred from the naming scheme
  • Protected access modifiers for a whitelist of methods/properties
  • Renaming the file in source-control to preserve history

The remaining percentage would be tidied up by hand. This generally included creating any interfaces needed, re-formatting code to benefit from type-inference and lastly fixing any bugs the TypeScript compiler found along the way!

The latter was the first sign our decision to migrate the codebase was indeed a valid one. The bugs were just simple spelling errors in function calls or chaining to base methods that didn’t exist – things the TypeScript compiler is great at giving visibility on.

After the conversion it was time to test the build output. Thankfully, given the output of the TypeScript build was so close to how the JavaScript codebase was originally authored, we were able to simply diff the combined outputs to get a very accurate idea on where our test efforts should lie. We found a few issues as a result of the diff but in terms of bugs raised in test, there were none.

The process, including modifying our build systems, testing the build output and writing new interfaces, took around 10 days. So having the script do most of the legwork enabled us to average around 6,000 lines a day during the conversion itself.

Was migrating to TypeScript worth it?

Absolutely. There’s no doubt, the answer is yes. Working on a large codebase that’s growing as fast as ours, with multiple developers active across different projects, it’s very important to get the quality right up-front. Having a type system running checks that previously involved a very manual process in QA is invaluable. It also allows us to take a much bolder stance when designing new components thanks to the introduction of interfaces, which we use heavily.

What next?

Having learned a lot with TypeScript, we’re currently migrating our workflow away from being based around MSBUILD & Custom Visual Studio Plugins over to instead be based around Gulp & Node, so we’ll share more on that in the near future.