TypeScript definitions for ExtJS 5

extjs, typescript

Solution

I started researching this question in earnest, but found the search results rather unfulfilling.

First of all, here is a small discussion which provides some insight into Sencha's view on TypeScript.

While I couldn't find anything specific to ExtJS 5 (my apologies), I did find this link, which claims to generate TypeScript declaration files using a process that starts with ExtJS documentation. The examples target ExtJS 4.1, but perhaps it could work with ExtJS 5. If so, it would solve your problem. That certainly isn't an answer, but perhaps it's a lead.

As an aside, the conversation referenced above didn't sit right with me. It begins with a seemingly innocent request for Sencha to consider the potential that TypeScript provides for static tooling.

TypeScript

I just spotted TypeScript (http://www.typescriptlang.org/), and it looks promising. Has anybody had a chance to play around with it yet? I want to understand if it would be possible to produce a TypeScript declaration file to declare all the types from the Ext JS and Sencha Touch frameworks. I'd love to have better static analysis and tool support for my Sencha development work.

Thanks!

This is the response from a Sencha Senior Forum Manager:

Just another thing to make things ugly [TypeScript]

[EDIT] Regardless of how many times I say this comment was obviously a personal comment, it's still personal. If you haven't talked to me or followed me on Twitter or anything, I'm anal about my code and the syntax that TypeScript (even ES6) is ugly.

That's pretty harsh!

I don't know the forum manager personally, so I am not going to speak to his particular bias against TypeScript. But I do think I can provide some insight into why Sencha representatives might not be rooting for it's success. Perhaps this will help you understand why it might not be a high priority for many people to create a definition file for ExtJS 5.

Please note that I could be wrong and there is an ExtJS 5 definition file out there that just hasn't made it to DefinitelyTyped yet. My search was far from exhaustive.

TypeScript

Here is a simple example of the model of object-oriented programming that TypeScript uses.. Notice that a constructor is a function which returns an instance whose state has potentially been modified or specialized from that of its prototype:

function Mammal() {
    //...  
}

The constructor's prototype property, which happens to be the prototype of the object returned by the constructor, can then extended with methods and properties (in the ES5 Object.defineProperty sense). The members that are declared on the prototype do not have to be recreated for every instance created by the constructor:

Mammal.prototype = function giveBirth() {
    //...
}

In this sense, the constructor is playing the role of a class, and the structure of its prototype property defines the type of object that is created by the constructor. While this pattern is quite verbose in ES3 and ES5, especially when adding in the additional machinery required for inheritance, it is the pattern used by ES6 to define the notion of a class. Therefore, it is the pattern used by the TypeScript compiler to compile a class.

For a more complete treatment of this form of classical object-oriented programming in JavaScript, along with techniques for making classical inheritance more succinct, see this post by Douglas Crockford.

What's noteworthy is that the notion of a type exists only at design time, and is enforced by the TypeScript compiler to help you write sturdier code.

ExtJS

Before TypeScript existed, I had become familiar with the model of classical inheritance employed by Sencha's ExtJS framework. This model provides a means for defining classes and creating instances from their corresponding types using several patterns, including the module pattern and the prototype pattern and the factory pattern. If you are an ExtJS programmer, you'll find these patterns quite familiar, but for reference, please refer to the appropriate sections of Learning JavaScript Design Patterns by Addy Osmani.

As a pure JavaScript developer, this method of classical object-oriented programming is powerful. It is similar in many respects to the model of classical object-oriented programming used by the TypeScript compiler, but with one key difference. In ExtJS, a class and its type are known to the framework, and therefore exist at run time. One of the best things about ExtJS is that it simulates the syntax of creating a class, much like one might do in Java or C#. But it is pale in comparison to the method of specifying a class in TypeScript.

When first introduced, I was so enamoured by the method of class definition employed by ExtJS that I created a library of my own called classical. I was inspired enough to create my own library in order to explore and extend class definition in JavaScript, and to implement it for my own edification. If you click the link above, you'll notice that the project has evolved away from an ExtJS-like class system, and into a base class library for TypeScript.

Why the change?

For starters, TypeScript provided a model of object-oriented programming which not only allowed me to utilize familiar OOP design patterns, but also provided me with a static type system and all the design-time tooling that went along with it. When first discovering TypeScript (version 0.8), my initial reaction was to create a type definition file for classical, which would be a similar (but much simpler) endeavor to creating one for ExtJS. After I had completed this task, the syntax of the resulting library was an utter disaster! I'd like to explore what went wrong, and I'll do so with a simple example from ExtJS.

This code is taken from the discussion mentioned above, and looks like a standard ExtJS class definition:

Ext.define('WebApp.model.RenderableRecord', {
    extend: 'Ext.data.Model',
    idPropert: 'id',

    isRenderableRecord : true,

    fields: [
        { name: 'id', type: 'string' },
        { name: 'name', type: 'string' },
        {
            name: 'renderable',
            convert: function (val, model) {return val;}
        },
    ],

    renderItems: function (renderer: Function) {
        var me = this;
        return function (config: Object) {
            renderer(me.get('renderable'), config);
        }
    },

});

Consider the interface that is defined by the prototype above. If static typing in TypeScript was desired, one might create an interface that looks something like this:

module WebApp {
  module model {
    export interface RenderableRecord extends Ext.data.Model {
      idPropert: string;
      isRenderableRecord: boolean;
      fields: Array<Field>;
      renderedItems(renderer: Function);
    }

    //Assume Ext.data.Model and Field are defined already
    //and that the Field interface looks something like this:
    export interface Field {
      name: string;
      type: string;
      convert: Function;
    }
  }
}

Not only would that interface have to be defined alongside the ExtJS definition, but instances would have to have their type specified twice, once as WebApp.model.RenderableRecord (or as a string of the same name when calling Ext.create) and then again by casting it to the appropriate TypeScript type. That's a lot of work to get static typing that is, as a result of the casting, still error-prone!

So what's the problem?

The problem is that there are two type systems in play. One is the design-time type system enforced by the TypeScript compiler. The other is the run-time type system defined by ExtJS. These two type systems are very similar in regard to the way they are implemented, yet they each have a distinct syntax, and therefore have to be specified seperately. Much of the value of a static type system is lost if it two copies of every interface have to be maintained.

Here is a more complete treatment of the hurdles that one must overcome when integrating TypeScript and ExtJS. It also references the GitHub project above. The author concludes that

Unfortunately, TypeScript and ExtJs do not seem to work too well together.

The bottom line is that ExtJS and TypeScript both define their own type systems, which don't quite play by the same rules. Therefore ExtJS and TypeScript are fundamentally incompatible with each other...

...okay fundamentally is too strong a word, but it takes a lot of work to use the two tools together effectively. So if I was a Senior Forum Manager for Sencha, I might not be rooting for TypeScript either.

Personally, I prefer the ES6 preview, the static type system and the design-time tooling provided by TypeScript. And it's a shame I have to even choose because the two aren't of the same type - one is a framework and the other is a language. And some folks sure do go to great lengths to make them compatible.

ExtJS is a powerful JavaScript framework, which I'm sure has only grown richer in time. But as it is, ExtJS is at it's best when used as a JavaScript framework. Or to quote that same forum manager:

...you can write correct and productive JavaScript without the need of any compiler like coffeescript or typescript.

ExtJS provides one approach to classical object-oriented inheritance in JavaScript as a framework. TypeScript provides a second approach as a language. If you're interested in TypeScript, take a look at classical. It is far from a professional framework like ExtJS, but it does provide an opinion about what tools might look like when built for TypeScript developers.

Problem

Is anyone working on TypeScript definitions for ExtJS 5? I keep checking DefinitelyTyped but there is no activity: https://github.com/borisyankov/DefinitelyTyped/tree/master/extjs

Original source