Typescript and Google Closure

 ̄綄美尐妖づ 提交于 2019-12-05 14:27:16

The definition of __extends has an issue which is most likely causing the error you see.

var __extends = this.__extends || function (d, b) { ... };

The this.__extends reference is meant to be the same thing as window.__extends, however Closure-compiler does not know (or ever even tries) to realize that the reference to this in the global context is in fact the window object. Compiled with --warning_level=VERBOSE the compiler will emit the warning:

Dangerous use of the global this object at line 1 character 16
var __extends = this.__extends || function (d, b) {
                ^

In addition, the this.__extends is a reference to an external/undefined property and the compiler is also warning about that on VERBOSE level.

I've modified and annotated the definition to compile without warnings using the Closure-compiler Service UI:

// ==ClosureCompiler==
// @compilation_level ADVANCED_OPTIMIZATIONS
// @warning_level VERBOSE
// @output_file_name default.js
// @formatting pretty_print
// ==/ClosureCompiler==

var __extends = window['__extends'] || function (d, b) {
  /** @constructor */
  function __() { this.constructor = d; }
  __.prototype = b.prototype;
  d.prototype = new __();
}

/**
 * @constructor
 * @extends {String}
 */
function foo2() {this.foo = 'bar'; }
__extends(foo2, String);

var bar2 = new foo2;
alert(bar2.toLowerCase);

A JSFiddle of the modified and compiled code

Ok I found the problem.

As I said earlier, b is undefined in :

var __extends = this.__extends || function (d, b) {
   function __() { this.constructor = d; }
   __.prototype = b.prototype;
   d.prototype = new __();
}

When typescript "compile" into javascript, if you got one namespace by project but that you write all classes related to this namespace in separated files, Typescript do the following in the final generated js file :

var namespace;
(function (namespace) {

    var Class1 = (function (dependency) {
        [...]
        return Class1;
    })(namespace.dependency);

    namespace.Class1 = Class1;
})(namespace || (namespace= {}));

var namespace;
(function (namespace) {

    var Class2 = (function (dependency) {
        [...]
        return Class2;
    })(namespace.dependency);

    namespace.Class2 = Class2;
})(namespace || (namespace= {}));

var namespace;
(function (namespace) {

    var Main = (function (dependency) {
        [...]
        return Main;
    })(namespace.Class2);

    namespace.Main = Main;
})(namespace || (namespace= {}));

I don't know exactly how its works but somewhere google-closure-compiler removed some classes even if there is no problem with this code and JS can handle it. So some dependencies was missing and b was undefined.

So I found that if you declare your namespace like the following, you will not encounter the error anymore (closure will keep all your classes in the final obfuscated js file as long as the "Main" class is used or that you keep a reference of your namespace in the global window object) :

var namespace;
(function (namespace) {

    var Class1 = (function (dependency) {
        [...]
        return Class1;
    })(namespace.dependency);

    namespace.Class1= Class1;

    var Class2 = (function (dependency) {
        [...]
        return Class2;
    })(namespace.dependency);

    namespace.Class2= Class2;

    var Main = (function (dependency) {
        [...]
        return Main;
    })(namespace.Class2);

    namespace.Main = Main;
})(namespace || (namespace= {}));

I think I will open an issue on typescriptlang.org. It's optimizing the generated file size by the way.

Thank you for your answers!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!