Add compiler flag(s) to prevent extra code generation (extends, super, etc.)?

Topics: General
Jul 10, 2013 at 10:24 PM
Edited Jul 10, 2013 at 10:27 PM
Some frameworks, such as Ext JS or Sencha Touch, have their own class system. Trying to work with these in TS is proving difficult, because TS generates it's own wrapper logic for things like extends, super(), module, etc. These all affect the way the object is actually defined/structured in the JS, which won't work with the framework's class system.

Could compiler flags be added to prevent TS from generating these things? Basically, in this case I'd want it to just compile the TS that is there to JS, but not add anything extra to the compiled output.

In other words, if I say "class Foo extends Bar { ... }", don't create the extends wrapper and prototype merging. I want my IDE to know I'm extending the class, but I don't need the actual extends logic in the JS. There are other things going on that will actually handle the inheritance at runtime.

It seems like this wouldn't be difficult to do, and in addition to the large pool of developers using Sencha's platforms, I'm sure there are other cases (even just generating example code that doesn't need the wrapper logic) where this could be useful. Obviously by default it would keep working the way it does now. The new flag(s) would just be there for cases where someone actually needs to omit the extraneous code.
Jul 11, 2013 at 2:42 AM
+10

I would really love to have this feature. Without it, I can't mix Ext/Sencha and Typescript.

Personally, I'd prefer something I can put in my Typescript source files rather than a compiler flag - because there are some classes in my solution where I want to use Ext's patterns, and others where Typescript's is fine. It would also make it easier to share source files and know they will compile correctly on other's computers.

Something like the following would be ideal:
class Snake extends(Ext.extend) Animal {
where the "parameter" to the extends keyword is the existing function to call (expect the same signature as __extends). It would default to Typescript's own __extends if not provided.
Jul 11, 2013 at 11:45 AM
You can override the __extends function... Once you start working with typescript class system + modules loaders maybe you will not need Extjs class system....

I figured out how integrate Ext 3.4 with typescript just overrinding __extends + Ext.create functions
Jul 11, 2013 at 3:12 PM
First, I'm curious how you overrode __extends and what you did, because I tried everything, including just making my version of __extends do NOTHING, and it still wouldn't work.

Second, we really shouldn't have to manually override __extends and try to outfox TS in the generated JS. Just letting us omit this extra logic would seem to be a lot easier and more transparent.

For example, consider this TS:
declare module MyApp.foo {
    export class MyBaseClass {
        doSomething(): void
    }
}

module MyApp.foo.bar {
    class MyClass extends MyApp.foo.MyBaseClass {
        constructor() {
            super();
        }
    } 
}
The resulting JS is:
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var MyApp;
(function (MyApp) {
    (function (foo) {
        (function (bar) {
            var MyClass = (function (_super) {
                __extends(MyClass, _super);
                function MyClass() {
                    _super.call(this);
                }
                return MyClass;
            })(MyApp.foo.MyBaseClass);
        })(foo.bar || (foo.bar = {}));
        var bar = foo.bar;
    })(MyApp.foo || (MyApp.foo = {}));
    var foo = MyApp.foo;
})(MyApp || (MyApp = {}));
I'd like to be able to tell the compiler to remove everything that it can from all this, and just give me something like:
var MyClass;

MyClass = (function() {

  function MyClass() {}

  return MyClass;

})();
Basically don't spit out anything for the module wrappers, extends, super, etc. I'm telling the compiler that something else is dealing with all of this. Since it doesn't really affect the core of the generated code, only the outer wrappers and the way the JS "class" is defined, I would think this should be pretty easy do it.
Jul 11, 2013 at 4:33 PM
Edited Jul 11, 2013 at 4:35 PM
Here is the code to intercept __extends function. I didn test with Ext4.
module Ext {
    export class TypeScript {

        private static _extCreate = Ext.create;

        static extExtend(base: Function, config: any) {
            var cls = Ext.extend(base, {
                constructor: function (config) {
                    //alguns componentes (ex:splitRegion) utilizam a propriedade initialConfig
                    this.initialConfig = config;
                    //nao chamar super class agora porque as classes
                    //que derivam irao setar propriedades 
                    //sera necessario utilizar tsInit
                },
                tsInit: function () {
                    TypeScript.initConstructor(this, cls);

                }
            }, config);

            return cls;
        }
        static initConstructor(cmp : any, cls : Function) : void {
            Ext.apply(cmp, cmp.initialConfig);
            
            //as classes deverao chamar initialize apos o construtor
            (<any>cls).superclass.constructor.call(cmp, cmp.initialConfig);
        }
       static createComponent(config, defaultType) {
           var cmp = TypeScript._extCreate.call(Ext, config, defaultType);
            if (cmp.tsInit) {
                //chamar apenas uma vez o construtor 
                cmp.tsInit();
            }
            return cmp 
        }
        static tsExtend(derived : Function, base : Function){
             function __() { 
                //hack necessario para Ext4
                this.constructor = base.prototype.constructor; 
            }

            __.prototype = base.prototype;
            derived.prototype = new __();
        }

    }
}

//intercepta metodo de extensao do TypeScript
var __extends = this.__extends = Ext.TypeScript.tsExtend;

//interceptar funcoes do Ext
(<any>Ext).create = (<any>Ext).ComponentMgr.create = Ext.TypeScript.createComponent;
//criar classes interceptadas
(<any>Ext).TsContainer = Ext.TypeScript.extExtend(Ext.Container, {});
(<any>Ext).TsBoxComponent = Ext.TypeScript.extExtend(Ext.BoxComponent, {});
(<any>Ext).TsPanel = Ext.TypeScript.extExtend(Ext.Panel, {});
(<any>Ext).TsTabPanel = Ext.TypeScript.extExtend(Ext.TabPanel, {});
(<any>Ext).TsToolbar = Ext.TypeScript.extExtend(Ext.Toolbar, {});
(<any>Ext).TsWindow = Ext.TypeScript.extExtend(Ext.Window, {});
(<any>Ext).tree.TsTreePanel = Ext.TypeScript.extExtend(Ext.tree.TreePanel, {});
(<any>Ext).menu.TsMenu = Ext.TypeScript.extExtend(Ext.menu.Menu, {});
//necessario para classes que derivam de Observable e desejam adicionar construtor padrao
(<any>Ext).util.TsObservable = Ext.TypeScript.extExtend(Ext.util.Observable, {} );
(<any>Ext).form.TsFieldSet = Ext.TypeScript.extExtend(Ext.form.FieldSet, {});
(<any>Ext).form.TsTwinTriggerField = Ext.TypeScript.extExtend(Ext.form.TwinTriggerField, {});
(<any>Ext).grid.TsGridPanel = Ext.TypeScript.extExtend(Ext.grid.GridPanel, {});
(<any>Ext).grid.TsEditorGridPanel = Ext.TypeScript.extExtend(Ext.grid.EditorGridPanel, {});