晚上好.
我有一个 - 看似 - 无意义的问题出现在从Typescript项目编译的Javascript输出中.这个问题似乎很复杂,但我会尽量简短明了.
我的Typescript项目名为"MyApp"(完全面向对象,在Visual Studio 2013中开发)设置为编译为单个输出文件(main.js,ECMAScript 5),然后在浏览器中运行.没有使用模块加载软件(如AMD),我希望保持这种方式.项目中引用的所有打字稿文件(.ts)都是自动编译的,无需手动引用它们///
.
我有这个文件(Score.ts),深入到命名空间结构的一个级别:
居于App_Script/Score.ts
namespace MyApp.App_Script { export class Score { protected tracks: MyApp.App_Script.Entities.Track[]; ... } }
命名空间结构反映了目录布局:
MyApp |-- App_Script | |-- Entities | | |-- Track.ts | | |-- Note.ts | | `-- ... | |-- Loader.ts | |-- Score.ts | `-- ... `-- main.ts
所述Score
类在main.ts文件(该文件可以被认为是单数的"入口点"到应用程序),其内容被封闭到MyApp的命名空间实例:
main.ts
namespace MyApp { import Score = MyApp.App_Script.Score; var score: Score = new Score(); score.init(); ... }
上面的代码(以及上面目录布局中显示的所有其他依赖项)编译没有问题,并且正确运行,漂亮和流畅.但是,在Score.ts中,我希望import
Track类避免必须输入数十次完全限定名称:
居于App_Script/Score.ts
namespace MyApp.App_Script { import Track = MyApp.App_Script.Entities.Track; export class Score { protected tracks: Track[]; ... } }
此代码也可以正确编译,无需消除任何错误,按预期创建指定的输出文件.我的Typescript源文件中的一切似乎都很好,因为所有与Typescript相关的工作都完美无缺:没有报告语法错误,并且自动完成在导入的Track
类以及所有其他代码上正常工作.
但是当在浏览器中运行时,
main.js:无法读取未定义的属性'Track'.
......这也难怪,因为这是指定的输出JavaScript文件看起来像的开始的憎恶(这些都是非常输出第一行):
main.js
var MyApp; (function (MyApp) { var App_Script; (function (App_Script) { var Track = MyApp.App_Script.Entities.Track; // PLEASE LEAVE var Score = (function () { function Score() { this.tracks = []; for (var i = 0; i < 4; i++) { // shouldn't this be "new MyApp.App_Script.Entities.Track()"? // if I rewrite it manually, it works this.tracks.push(new Track()); } } return Score; })(); App_Script.Score = Score; })(App_Script = MyApp.App_Script || (MyApp.App_Script = {})); })(MyApp || (MyApp = {})); ...
对于定义Track
实际上是对底部的编译输出(当它应该是在顶部):
main.js
... var MyApp; (function (MyApp) { var App_Script; (function (App_Script) { var Entities; (function (Entities) { var Track = (function () { function Track() { ... } return Track; })(); Entities.Track = Track; })(Entities = App_Script.Entities || (App_Script.Entities = {})); })(App_Script = MyApp.App_Script || (MyApp.App_Script = {})); })(MyApp|| (MyApp = {})); ...
这是我观察到的:如果你import
是一个班级,那很好(得分是从main.ts导入而没有问题).如果您import
是包含在其他位置导入的导出类的命名空间中的类,则编译器会在不报告任何错误的情况下阻止不可用的代码.
这是TypeScript编译器中的错误,还是只是我遗漏的一些完全无关紧要的东西?我不希望使用模块加载系统,因为这似乎是编译器的问题,代码将在浏览器中运行.
IMO import
应该在编译期间简单地用受限制的名称替换受影响的类名,而不是在输出Javascript代码中引入其他指令.
这是TypeScript编译器中的错误吗?
没有
或者这只是一件我完全无聊的事情?
是
我不想使用模块加载系统,
您可能应该,因为您有文件排序问题
import应该在编译期间简单地用受限制的名称替换受影响的类名,而不是在输出Javascript代码中引入其他指令.
那是不对的.考虑一下这样的代码:
namespace Z { export var A = 10; } namespace X { import Y = Z.A; namespace Q { let Z = { A: 20 }; // If we replaced 'Y' with 'Z.A', as proposed, 'a' would be 20 // when it should be 10 let a = Y; } }
这里的问题是TypeScript不会自动猜测应该连接文件的顺序.
修复方法是向///