PureMVC for TypeScript

PureMVC for TypeScript

As you may already know, TypeScript is a new programming language announced on October 1st,2012. It is written at Microsoft by Anders Hejlsberg (designer of C#, Delphi, Turbo Pascal) with specifications published under an Apache License. Its goal is to output JavaScript from a superset of the language which allows compile-time type checking, classes, interfaces, modules and more while still understanding vanilla JavaScript.

In the week TypeScript was announced I contacted Cliff Hall to tell him I was ready to port TypeScript to PureMVC. He immediately told me that he was ok, probably because he's a well known supporter of «languages that compile-to-JavaScript».

I first tried to develop using Visual Studio 2012 and its dedicated TypeScript module which may had helped a lot to start with TypeScript, but I'm on Windows XP at home and VS 2012 simply doesn't run on it. As a resulting consequence, I made my work using Webstorm for JavaScript and the Node version of the TypeScript compiler (let me know if I missed something specific to Visual Studio 2012).

For the rest, I was lost at least one hour or two before starting the work because of lack of any existing documentation, but using stackoverflow.com and examples from the official TypeScript website, I quickly found all I needed to start with this new language.

Port to PureMVC

For the work on the framework itself, I decided to merge PureMVC ActionScript 3 Standard Framework and my own PureMVC JavaScript for Objs Standard Framework so it has typing from AS3 and required idioms from JavaScript.

As a result of this work I produced three PureMVC TypeScript repositories:

The PureMVC EmployeeAdmin demo can of course also be tested live.

Update: Cliff Hall made the official announce for it on the PureMVC website.

live puremvc employee admin demo screenshot

I think that ports will be given status «development» on PureMVC as TypeScript itself is still only in «preview stage» even if produced JavaScript is ready to use for production. This said I will update both ports and demo each time TypeScript receives an important update. I count on PureMVC users and my readers to ping me or pull a request on Github if the framework needs an update.

TypeScript Modules

TypeScript supports compiling to JavaScript AMD and CommonJS module format using a simple syntax.

I made it so mandatory to create a PureMVC library designed to use TypeScript integrated module definition. So each TypeScript class is thought as a part of a named puremvc module. Exact code for the SimpleCommand class is:

module puremvc
{
  "use strict";
 
  /**
   * A base ICommand implementation.
   * 
   * Your subclass should override the execute method where
   * your business logic will handle the INotification.
   */
  export class SimpleCommand
    extends Notifier
    implements ICommand, INotifier
  {
    /**
     * Fulfill the use-case initiated by the given
     * INotification.
     * 
     * In the Command Pattern, an application use-case 
     * typically begins with some user action, which
     * results in an INotification being broadcast,
     * which is handled by business logic in the
     * execute method of an ICommand.
     * 
     * @param notification
     *     The INotification to handle.
     */
    execute( notification:INotification ):void
    {
 
    }
  }
}

Here comes my first headache using TypeScript compiler : it supports to compile a list of files but it can't recursively look for files to compile in a target source directory. My first work was so to create an Ant Task for that.

Also, TypeScript compiler has two parameters that may helped in creating a single module file for the PureMVC library:

--out
Output a single file from multiple TypeScript input files. This leads to optimize the generated JavaScript code a little. So it definitely has to be used.
–module
May be set to AMD (Asynchronous Module Definition) or CommonJS to output respective module compatible code.

I first thought this was as easy as using those two parameters at the same time, but it was not.

I googled it a lot, results were updated near every day, but TypeScript currently is unable to create a single file from multiple TypeScript files of the same module. This only works in some conditions (using fake imports) which forces to write a clunky code which I definitely don't want for PureMVC framework classes files (let me know if you find an acceptable solution).

I so have created a dedicated Ant build which does the simple job of adding the AMD module wrapper on the compiled JavaScript (but still non-minified) library.

I will definitely add an option for the build to output a CommonJS module version of the framework before committing to PureMVC Github. I would in this case also create a dedicated version of the tests for it to consume PureMVC library and unit tests as CommonJS modules.

Build Ant Task

Build the project

  1. To build the project, you only have to install your TypeScript compiler of choice (as explained mine was Node one), Ant, a JDK because Ant won't run without a simple JRE (with a good connection this only takes few minutes). Everything else you need is included in the build directory of the project.
  2. Renames the user.properties.sample file to user.properties, open it and add to the file the path of the TypeScript compiler on your system (the user.properties.sample file is well documented on how and why).
  3. Run «ant build» from the command line from the root directory of the project. It will generate both framework and unit tests JavaScript libraries.

TypeScriptRecurse Ant macros

If you have a look at the buildfile for the PureMVC TypeScript standard framework (both of standard and multicore build.xml files are exactly the same) you will note two macrodeftags. The first is the <macrodefname="TypeScriptRecurse"/> tag.

As documented it «recursively reads a source directory for TypeScript files, generates a compile list in the format needed by the TypeScript compiler adding every parameters it takes and finally compiles it». This means that it wraps the TypeScript original Ant exec call respecting its original parameters (excepted watch for obvious reasons) but at the difference that its src argument can only be a directory path and that it will recursively read each TypeScript file in this directory to add it to the generated JavaScript output.

DefineAsAmdModule

The second macro is defined by the <macrodefname="DefineAmdModule"/> one.

As documented «when using multiple files TypeScript compiler is unable to add the correct module definition when targeting a the single generated JavaScript file. We have to manually add the standard AMD define wrapper around the generated JavaScript module».

So this one is really simple in its design. It wait for the TypeScript compiler to generate the single JavaScript file, opens it and add the right module definition into it adding the module name using an argument the user passes to the macro.

Minification

The minification is made on the TypeScript to JavaScript generated file using YUICompressorand YUIant.

Here we can measure advantages of TypeScript against lets say Dart or GWT as the resulting file size is only 9KB. The same weight as the PureMVC JavaScript port.

EcmaScript 5

The only extra parameter that makes sense to set in our case is the --target parameter. It is set to ES5 which means that the code has to respect the EcmaScript 5 syntax specification to compile.

Note that both PureMVC library and Unit Tests would have compiled using ES3 (default value for this parameter) as the project do not use any EcmaScript 5 specific code. But setting it to ES3 also deactivate support for the extras verification offered by the “use strict” tag you may have seen on every file of the framework. If you don't know what the “use strict” is intended for you can read an article from John Resig on this subject.

If anyone asks me, I will add an option to the DefineAsAmdModule macro for it to add «use script» tag to the module context instead of having to write this tag on top of every TypeScript class, which is really annoying.

Declarations file

A big advantage of TypeScript is that it allows to use existing JavaScript libraries directly from TypeScript code without having to adapt the libraries for it to work. But as existing libraries aren't typed, nor has interfaces or classes, you have first to design what TypeScript developers named a «declarations file» (with a *.d.ts extension). that will offer the compiler away to compile-time check your code without checking all the real external library (optionally crappy) JavaScript code. This file contains no more than something equivalent to interfaces code defining public API of the existing library.

Each standard and multicore PureMVC libraries came with a description file that you may find beside the plain and minified JavaScript files in the bin directories of the projects.

The TypeScript compiler helps a lot by creating the description file using an optional --declarationsparameter but as it simply omits to add required interfaces code into it, I had to add this part manually to the descriptions file of the PureMVC project.

Unit Tests

This would have totally makes sense to keep existing unit tests written in JavaScript for the existing PureMVC JavaScript Framework for Objs. I even used them when converting the PureMVC framework to TypeScript to be sure not to loose anything compared to the JavaScript port. But this would really have been cheating with the quality of code we are used to on PureMVC ports. So I written all Unit Tests in TypeScript right after the tests passed using JavaScript unit tests.

For this, today TypeScript only have a tiny Unit Test framework which lacks all the existing assert methods of the «jUnit like» unit testing we are used to on PureMVC. It particularly can't output the dedicated assert message which may lead to a loss of information regarding existing other PureMVC ports. I so have decided to use YUITestwhich I already have used with success on PureMVC for Prototype, and PureMVC JavaScript for Objs by the past. It is clear, simple and can be executed in the browser which is a mandatory for any JavaScript code that is targeted for the web.

As nobody still have made any «declarations file» targeted to use YUITest in TypeScript I had to design a minimal YUITest.d.tsextension file which defines all the asserts from the Assert class used by the PureMVC framework (and even those not used).

unit test screenshot

As you may see on the results for the PureMVC Multicore TypeScript framework unit tests output is counting 51 Unit Tests and of course all passes.

As explained, both Unit Tests and PureMVC library are written using AMD modules. I so have designed the test HTML page to use Require.js to load both PureMVC library and Unit Tests generated files. It proves that all PureMVC can be loaded as a module and works as expected when used from another TypeScript module.

Namespacing

In TypeScript namespacing is made using module names. Here, finally, each class of the framework is using the puremvc namespace.
I hope having I missed something obvious but TypeScript doesn't seems to support any smart way (like AS3, Java or C# does) to import classes of a specific namespace (from an imported module using the import directive) without having to prefix each class reference with its module namespace. This means to write puremvc.Model instead of only Model in the context of the class that imports a module which finally is really annoying.
I hope it may change in a near future.I will report as much as issues I noted to the TypeScript team while it still preview.

Employee Admin Demo

The Employee Admin demo was ported to TypeScript using the PureMVC JavaScript for Objs Employee Admin demo.

As it uses jQuery I had to download the jQuery TypeScript descriptions file offered on the official TypeScriptwebsite.

The demo also uses jQuery UI and jQgrid. I may had created a descriptions files for each, but sadly a TypeScript descriptions file can't overrides another one, so jQuery UI or jQgrid overrides on jQuery has to be made by hand on the previous jQuery descriptions file. Some developers already have noted this problem and it will probably be pushed as an issue to the TypeScript team. I will push it by myself or simply vote for it depending on the status of this issue on CodePlex.

The JavaScript file for the demo is generated using the same Ant tasks I made for the framework itself and it is loaded with PureMVC library as AMD modules using Require.js.

3 thoughts on “PureMVC for TypeScript

  1. Hi Frederic,

    I was practicing with typeScript and PureMVC for a while and made a demo of the Simon Says game with PureMVC. After I finish new version of typeScript came out (V 0.9.x) witch makes a lot of new interesting changes, specially on using modules or requires for AMD.
    So I decide to port the game to this new version of TS. As I was porting the game I realice that I could also do an entire refactoring of PureMVC to be AMD compliant with the advantages that this offer.

    So finally I finish and I have it on my github. I also have a project with the source form pureMVC framework that you can see it here:

    https://github.com/area73/typescript/tree/master/pureMVC-AMD-TS_V-0.9

    and this is where the simon says example app is located:

    https://github.com/area73/typescript/tree/master/simon-says-ts-v_0.9.x

    I didn’t want to make a fork of your project, first of all because I’m kind of new at github and I don’t know exactly how it works, and also because I don’t know if this project matches the scope of yours.
    I hope this work can help you, I don’t know if you need contributors or if I can help you any way, if so please let me know and I’ll be glad to help you.

    Thanks for your work

  2. Hi Rodrigo,

    You’re right and up to date, it’s a pretty good idea to update the PureMVC TypeScript port to TypeScript 0.9.x (they just updated it to 0.9.0.1 today).

    I quickly had a look into the new features and saw they made a syntax change in the module definition to have something near compatible with both AMD and CommonJS syntax like you said.

    I also quickly had a look into your work. Thank you to have cited me in the contributors list in an humorous way.

    Before I can integrate your work, I will first have to figure out how the new syntax defines the «puremvc.*» namespace before each class. I saw in your example that it disappeared with the new syntax. We can’t directly use the raw module classes definition especially as Notification is a reserved keyword in ECMAScript 5.x as it is used by the new event system. I will also need to update all Unit Tests dependently.

    I will see what to do as soon as I can. Thank you for your help.

  3. Pingback: Extension to remove expanded images from Twitter | Tekool.net

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>