7 Months with TypeScript


Since December 2012, I have used TypeScript as my primary language while working on a large scale enterprise project due to ship next month. I want to share the details on how we are using TypeScript as a team and our workflow that has made our project a success.

TypeScript?

TypeScript is an open source language and compiler written by Microsoft that runs on NodeJS. The language is based on the evolving ES6 spec but adds support for types, interfaces that generates JavaScript (ES3 or ES5 dialects based on flag). TypeScript’s compiler is written in TypeScript and run on any compliant JavaScript runtime by default it is distributed as an npm on Nodejs. End of the day, JavaScript is generating JavaScript. For more information see wikipedia or typescriptlang.org.

Evaluation

In November 2012, we selected technologies and our initial evaluation of TypeScript proved surprisingly beneficial. While we evaluated Haxe, Dart, CoffeeScript, we quickly honed in on TypeScript given it is an ES6+ to JavaScript compiler. We wanted all code to be JavaScript but we wanted to inject structure into our development process and be able to lean on the compiler for validation and richer errors. Really our choice boiled down to either use JavaScript or TypeScript. From there we wrote several small scale prototypes and quickly exposed the following:

  • Validation – TypeScript enabled us to validate code usage cross-modules at compile-time. In assigning types to variables and to method arguments, we were able to effectively validate all call/get/set across every module, every build. If a property was set to type bbox.controls.Image, nothing would satisfy the compiler but an Image instance or a subclass.
  • Early errors – We would get very detailed errors from the TypeScript compiler and with the addition of types and interfaces, the errors got even more specific.
  • Zero calorie types – TypeScript’s types and interfaces evaporate at compile time leaving no trace of the language while generating clean JavaScript.
  • ES6 Today – TypeScript is based on ES6 with additions of types and interfaces. It let us write source in a modern dialect of JavaScript, yet output to compatible ES3, ES5 with a compiler flag. With support for a modern class syntax( constructor, subclassing, interfaces, export, modules ) it made code organization painless.
  • Build process – One of the first checkins and tests was to create a team build process with Ant. With a properly configured environment any developer could sync with SCM and build a working local server with all code packaged for development or production use. The build process integrates Less, RequireJS, Uglify2, TypeScript, template processing, and server generation.

Usage

In the months that followed our evaluation we settled into a team workflow with TypeScript that really benefited our project. The build process is at the center of development and our daily work. Every day looked like so:

  • Update from SCM
  • Run ‘ant all’ ==> Full build + start local server
  • Run ‘ant dev’ or ‘ant ts’ ==> Incremental build
  • Error at build or Test in Browser
  • Rinse & Repeat

build

I really enjoyed this model in that I found over time that we spent far less time in the browser testing than prior JavaScript projects. As the build would validate and catch syntax/interface/type/usage errors, we only browser tested when the build validated and worked. Once we all got better at decoding the TypeScript compiler output errors, we gained a level of productivity that I have not encountered in web development. It sounds odd to spend 5 seconds compiling but in the end it removed an entire class of useless testing of non-working code from our development schedule. This aspect alone saved us 2 months of time while dramatically improving the output code quality.

When we began development the quality and quantity of available TypeScript definition files was not ideal. Definitions allow you to strongly type the interface of JavaScript Libraries externally and thus your code must conform to the definition at compile-time. Since starting this project definitions have done a complete 180 with many contributions to Definitely Typed for just about any major or minor JavaScript library in existence. We utilized the definition files for Require, JQuery, Backbone, Bootstrap, Underscore, and EaselJS within the build process. To add a definition file you simply add the following reference statements to the file within your main .ts file:

Screen Shot 2013-06-25 at 5.53.00 AM

The references above are also how you add in any external libraries to TypeScript. In a way definitions, interfaces, and TypeScript classes all operate in the same way. In order to simplify our build process we unified all these calls in a single init.ts file which when called by the compiler loads in all TypeScript needed by the application. Even classes that are intended to be loaded via module are denoted here so that they are externally compiled to a module file. Note the use of the “export Class” syntax in this external module, this tells the compiler to keep the file external as a module and a compiler flag “–module amd” makes the compiler format modules to conform to either AMD or CommonJS format.

Screen Shot 2013-06-25 at 6.00.25 AM

Another elegant item is the module system in TypeScript for code organization. Each class and variable is exported into a path off the browsers window object making it global. We utilized the namespace ‘bbox’ for all classes and variables and with typing support, you can make a very well defined namespace for your application quickly. The module above starts in ‘bbox.controls’ and at runtime you can find this class exported to bbox.controls.Bounds. Considering we have 60+ classes to work with we used the module system to its limit and it never missed a step. You are free to export and type individual variables and whole classes this way so you are not locked into everything needing to be a class. In many ways a typed export variable works great for singletons within a module as it provide limits to the type written and location accessed. With the additions of modules and types, the way you work with JavaScript just changes and it is a blurry line what is considered bad practice. With a first class compiler that can detect overwriting an object with an array or a very specific class type, you begin to work differently as TypeScript induces its own working model as a language. It isn’t JavaScript, yet it is.

Over the course of development I found myself changing development strategies in terms of refactoring. I started to trust the compiler’s behavior to the point where I would intentionally change types, interfaces, and naming to break things in order to expose code affected. I would then correct all lines from the compiler output and refactor as needed. In many ways this has allowed me to work effectively within a larger codebase.

typescript

As for development environment, I went with Sublime Text 2 + TypeScript syntax, while the other developers on the team opted for JetBrains. I found Sublime to be a great environment for TypeScript, even without code completion, I had zero complaints. Given that the compiler can provide incremental compilation and richer ide integration I think it will be a matter of time before we see far more advanced TypeScript tooling in Sublime/Edge/Jetbrains offerings.

While I loved working with TypeScript (and will continue to do so) there is one escape hatch that every developer using it should understand. There are times when you will butt heads with the compiler and it will block your attempts to call a method or variable as typing information is unavailable. When this shows up, we found that associative array syntax would unblock the issue til we could fix thing up. Example: foo['myProperty'] foo['myMethod']() would allow you to access myProperty or myMethod on foo regardless of typing information. I know it sounds odd but just keep associative array syntax in your back pocket, you will need at some point.

Some project stats on the project:

  • 63 TypeScript Classes
  • 12 libs ( Underscore,Require , Bootstrap , Jquery , Backbone , EaselJS … )
  • All Build – 8 seconds
  • Dev build – 5 seconds
  • 149Kb Libs & 411Kb Classes

Summary

TypeScript has been a joy to work with over the past 7 months. Having had experience with types/interfaces in ActionScript/ES4, I took to TypeScript very rapidly as it supported the structure I needed, yet maintained the elegant flexibility of JavaScript. In many ways I know our choice in using the compiler really moved our project forward in both delivery date and in code quality. I cannot say I have ever been a Microsoft fan but TypeScript has ‘softened’ me, it is easily one of the best web technologies to arrive in the past 3 years. I am looking forward to working on more projects with it and evolving with the language/compiler ongoing.

This week I will be onsite at Build in San Francisco learning about generics in the 0.9 build and next month I will be speaking on TypeScript at both Senchacon and 360Stack.

Consider me a TypeScript fan.

Ted : )

16 thoughts on “7 Months with TypeScript

  1. Andrei Neculau (@andreineculau)

    #1 Can you summarize your team’s analysis of coffeescript, haxe, dart? I think of coffeescript as “simplify to amplify” and thus increase code quality – more readable, syntax is a natural tool, not a goal, whitespace make code fluent, etc.

    #2 “We wanted all code to be JavaScript” — can I ask why? it’s one thing if you think of “easier to debug production/browser builds” (when sourcemaps are not possible), but in this case you still don’t have with 1:1 source:build code

    #3 “lean on the compiler” — reminded me of http://www.infoq.com/presentations/Simple-Made-Easy — he has an analogy about cars and road fences; doing TDD/BDD and lean on tests for your code to do what it’s supposed to do.

    Disclaimer: I’m not a coffeescript troller :) I haven’t tried TypeScript, because I’m not a huge fan of typed languages, nor of any syntax stopper. The most common problem is reasoning a solution, and end up with a readable solution. Otherwise lots of devs can code magic, or have their flow annoyed by syntax alone or syntax-required boilerplate, and end up with poor code logic (my own limited conclusion towards me and others). Coffeescript is closer to KISS for me.

    PS: you seem to have a funny style guide :) whitespace inside parens, but no whitespace after colon (O.o)

    Reply
    1. Ted Patrick Post author

      Andrei,

      I personally love whitespace indented languages Python, Lua, Coffee. I feel that syntax is only one dimension of the problem and CoffeeScript has solved this elegantly. The problem is that syntax conversion cannot check the validity of code at compile time. This is where TypeScript is completely different and unique as the validity is in developer hands via types and interfaces.

      As for our eval of Coffee, Haxe, Dart, these all fall into non-js languages. Given the JS/ES skills on the team TypeScript was a great fit. Haxe is a hybrid generic language with great extern support but the lack of externs was a key issue there. Dart also lacked extern support when we evaluated it but now supports it.

      “JS Support” – We wanted to leverage existing knowledge on the team. Learning a new syntax was a barrier here. All of us had worked in JS and AS3 prior to this project and TypeScript falls between these two languages well. Also the generated code out of TypeScript was important here as it generates really readable clean js. Although we rewrite that within Uglify2, we wanted clean easily debuggable source. The TS compiler does generate sourcemaps as of 0.8.2 accurately so testing is simplified but given the code, I didn’t need to use them.

      Language choice is a very personal and team affair. I simply wanted to share my findings, clearly there are cases when TypeScript, CoffeeScript, JavaScript are more appropriate choices for development. Best tool for the job depends on the team skillset, the environment, and the project, for this work TypeScript was a great fit.

      Regarding my sub-par blog template, well it needs an update. :)

      Reply
    2. mindplay.dk

      Having worked with both CoffeeScript and TypeScript, I would say, there really aren’t a lot of similarities between the two – they both add OOP with classic inheritance, and that’s about where it ends.

      From my experience, I would say that CS and TS have very different objectives and solve very different problems – in two different worlds, if you will.

      CS is very focused on the “micro” problems with JS – syntax primarily, and inconsistency of certain operators, brevity, tidyness, and more legible code.

      This contrasts with TS, which is very focused on “macro” problems with JS – scalability (in terms of complexity) and maintainability (type checking, inference, automated refactoring) and as such is focused on solving problems with large, complicated codebases.

      Beyond introducing classical inheritance, CS doesn’t deal much with any of the “macro” problems, while TS on the other hand doesn’t really deal with the “micro” problems at all.

      If you write lots of scripts in the hundreds or low thousand lines, CS is probably going to give you more of what you need/want in the short run. If you write large, complicated software applications that run on the client, work in team, and have to grow and maintain these applications over years, TS is probably going to pay off in the long run.

      Ideally, I would like to see a language with TypeScript’s feature set and CoffeeScript’s brevity – to me, that would be the best of both worlds, but for now we have to choose.

      Reply
  2. Mike Keesey (@tmkeesey)

    “I will be speaking on TypeScript at … Senchacon”

    Have you or somebody figured out how to make Sencha and TypeScript play nice? It seems to me that the way ExtJS/Sencha classes and packages work (through string identifiers) is not compatible.

    Reply
    1. Ted Patrick Post author

      Mike,

      There is a new definitions file for Sencha ExtJS at Definitively Typed https://github.com/borisyankov/DefinitelyTyped/tree/master/extjs, it is about 1 month old and there are definitely areas where work is still needed. TypeScript is JS and given a base definition, you should be able to augment types within your app. You also have the choice as to where typing and interfaces are used. Ext.define actually creates a real js class from a js object, so you can work backwards using another class system. Sencha is really designed to be composition driven. It can make for some odd workflow but I plan to present my findings and the outstanding issues at my unconference session at Senchacon.

      Reply
      1. Roman Shelomanov

        Hello Ted, can you provide your findings and the outstanding issues about using typescript with extJs. Is it advisable to use the typescript with extJS for JS development accelerattion and script validation?

      2. Ted Patrick Post author

        One key issue is the definitions for ExtJS. Given that ExtJS is a composition driven framework and uses its own Class system, Typescript integration is a challenge as you end up fighting against how the framework wants you to work. What I have found is that a light proxy api in TypeScript allows you to use ExtJS and broker all data in an out of it. Rather than a pure definition, you end up writing a Class in TypeScript that calls ExtJS and brokers results. This way the definition is very light, overhead is very light and you can define how you want your team using the ExtJS API. In many cases, methods are highly overloaded… Ext.create( {} ) and Ext.define( {} )… these get all sorts of code pushed into them yet easy to make a class Text.createButton( {} ) or Text.createGrid( {} ) where injected data is typed and filtered. The overloading of create and define is very hard to build definitions. If you attempt to generate them the TypeScript compilation crawls to a halt at 30sec compile times. The same is also true with AngularJS. Any framework providing a meta-data driven developer API will run into TypeScript adoption issues but there are ways to work around that. My 2 cents, Ted :)

  3. Gastrok G.

    I am wondering why you chose to use Typescript when there is another much more powerful Microsoft technology available – in the form of Visual Basic 6 (VB6). As you might not know, VB6 compiles down to machine code and consequently runs many times faster than Javascript. You can take the output of the VB6 compiler and process it with LLVM to create authentic Javascript which will run in any internet browser cabin.

    Reply
    1. Ted Patrick Post author

      Gastrok,

      Obviously there are 1000 ways to do cross compilation but at the end of the day we were focused on what is best for our project and our team. With our team and VB6, we would be done sometime next year. :)

      Reply
    2. Jens Melgaard

      I did not just see someone recommend VB6 in the year 2013 did I?… Was that meant as a joke?… o.O…

      There is many cross language compilers that compile to JavaScript, but as the JavaScript developers say, if your target is the browser and/or JavaScript in general… Learn to write JavaScript!… (TypeScript at least allows you to learn JavaScript while being enhanced with types)

      Reply
  4. Rune Jeppesen

    Great post – have you tried Visual Studio 2012 or 2013 with Web Essentials as IDE? If so what makes Sublime Text/JetBeans better?

    Reply
    1. Ted Patrick Post author

      Better is subjective. I use a Mac and prefer a simple text editor to a full IDE. Others may disagree but that is my choice. I do expect the workflow with TypeScript to get much better given tooling support.

      Reply
  5. Eljay

    I think it is important to mention that TypeScript is pre-1.0. It is still undergoing developmental churn, and as a moving target, early adopters will have to be willing to be adaptive to the late-coming changes. That will change shortly, but for the nonce.

    CoffeeScript 1.6.3 is released, stable, mature. A point in its favor.

    Disclaimer: I’m a TypeScript fanboy. I haven’t used CoffeeScript, but what I’ve seen I like. Maybe someday we’ll have CoffeeTypeScript.

    Reply
    1. mindplay.dk

      CoffeeTypeScript… every week or so, I’m on Google checking to see if somebody has had that idea yet :-)

      TypeScript gets compared to CoffeeScript far too often – and usually by people who haven’t actually worked with TS, or at least not long enough to fully understand it. The way I see it, CS is primarily about pretty syntax, classic inheritance, and workarounds for error-prone and/or misunderstood JS features. While TS is primarly about incrementally “hardening” JS, making it self-documenting and to some degree “self-testing”, while preserving the semantics of JS.

      The way I see it, the only substantial overlap between CoffeeScript and TypeScript, is that they both introduce classical inheritance – and the only real similarity, is that they both obviously compile to JavaScript, with one important key difference, that TypeScript actually *is* JavaScript.

      In my opinion, if we could have a language with CoffeeScript-like syntax, but with all the features of TypeScript, we would really have something incredibly powerful.

      Reply
  6. Pingback: Setting up a Typescript Project Structure to make the compiler happy | Coding in the cloud

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s