For the past year and a half, my team at work have been using TypeScript to implement a large single page application in Backbone. We’re over three quarters of the way through the project, closing in our our first release and here are my thoughts on using TypeScript to date.
Reasons for choosing TypeScript
The company has settled on TypeScript for web programming due to a number of factors.
Firstly is the additional security/peace of mind provided by type checking. For example, this prevents a lot of mistakes in calling functions with the wrong parameters. It makes some refactorings easier, as the compiler can tell you when you’re calling functions that no longer exist or are passing the wrong types to a function.
A nice feature is that TypeScript has support for implicit interfaces. The compiler will figure out if a class implements an interface rather than requiring that the class declares a list of implements X clauses in its definition. This reduces the friction of dealing with the type system.
Better tooling. The idea behind this was that, given that TypeScript has a proper type system, this would allow better tooling such as Intellisense. The theory was that programming in TypeScript would be a better experience because the IDE would be better.
As an aside, I would question the value of Intellisense and the type of code it leads to. Take Java for example. When you combine Intellisense with modern IDEs’ ability to automatically import files, you greatly lower the barrier to coupling. It is no problem to include remote files, grab the inevitable Singleton instance, and execute large Law of Demeter busting method chains on them.
I think Java tools have given the ability to create larger programs than can be properly maintained.
These features were seen as key to creating a more maintainable source code base especially at large scale.
My Experience with TypeScript
In the end, the code had the same classes with the same class names but the class implementations were far more readable due to the OO nature of TypeScript and the ability to define and program to interfaces.
When we started on TypeScript it was version 0.8. The compiler was a bit rough then and crashed on some invalid input rather than reporting errors. It has been steadily improved since then and version 1.0 is perfectly fine for us, reporting the correct errors for all the previously crashing cases. Also the language has been added to and improved over time.
Things I didn’t like about TypeScript
Continuing with the last point, with some TypeScript features, you need to know what type of code was generated e.g. did a variable assignment get generated in the constructor or on the prototype. For example, this is necessary when integrating with Backbone. Instance variables in TypeScript are not defined on the prototype but instead in the constructor after the call to super. This means that they are not defined by the time the Backbone constructor is called. The Microsoft solution is to put the call to super in the middle of the constructor but this looks wrong to any Java programmer and I could see them inadvertently breaking the code by moving super to the top of the constructor.
TypeScript’s support for Generics was almost good but again there are some issues. The main one I ran into is that you can’t create a new instance of the generic type e.g. for a generic type T you can’t do
var x = new T(). There are ways around this by passing in functions that create objects but the code they lead to is fairly bad.
The idea that types would lead to better tooling didn’t pan out for us. Taking IDEs first, I think the main tool that supports TypeScript is Visual Studio. There is also JetBrains’ WebStorm. As IDEs go these seem perfectly fine. It’s a bit hard for me to evaluate this as I’m not a fan of large IDEs. One issue with these is that, especially in the case of Visual Studio, they require large license fees. I don’t like criticising tools on cost issues, as I feel that companies should treat these as a required cost of hiring programmers. Unfortunately, a lot of companies don’t, so if I’m required to buy a personal license, I much prefer to buy a license for a tool like Sublime Text.
TypeScript files import other files by means of a reference path at the top of the file. This is almost like Java except unfortunately the compiler does not enforce these, thus requiring them to be manually maintained. This is impossible to get right for a large project. The only essential ones are those for your base classes but if you leave out the others then IDEs have problems locating type declarations. If you have extraneous references that are not technically needed then this can lead to the TypeScript compiler generating invalid code that defines subclasses before their parent classes. When run, these cause runtime exceptions. Not a great situation.
Integration with Third Party Code.
I think there is a large risk in using these, given that they are neither maintained by the library owners in question or by Microsoft themselves. It is problematic to update the libraries as now you have to also update the .d.ts. files. Everything going well, the Definitely Typed version will be updated to the latest version but there are no guarantees. What happens if the maintainer of this repository gets fed up and stops updating the files?