白鹭引擎在2017年1月10日发布了 4.0 版本,将内部编译器提升到了 TypeScript 2.1 。 本文的主要目标是向开发者介绍这为开发者带来了哪些改变。
概述
在白鹭引擎 3.x 时代,引擎在执行构建命令时,使用的是内部定制的 TypeScript 1.8 编译器,“内部定制” 主要包括:
- 添加生成类名称注册功能,以便白鹭引擎的反射 API
- 根据依赖关系,进行自动的文件排序功能
- 优化一些底层输出逻辑,降低编译体积
在白鹭引擎4.0版本,我们将编译器版本从 TypeScript 1.8 提升到了 TypeScript 2.1,您可以从 TypeScript 官方文档 了解从 TypeScript 1.8 至 2.1 引入的全新特性。除此之外,我向开发者简单介绍一些常见的技巧和问题解决方式
新特性
允许使用 ECMAScript 6 的绝大部分新语法
您需要在tsconfig.json
中添加以下内容
{
"compilerOptions": {
"target": "es5",
"lib":[
"es5","dom","es6"
]
}
}
当您添加es6
字段后,就可以在白鹭引擎中使用全部 ES6 的新特性。ES6 功能列表您可以参见 ECMAScript 6 入门 这篇文章。
ECMAScript 6 的新特性中,属于语法的部分会由 TypeScript 直接编译为旧浏览器兼容的实现。属于 API 的部分是需要开发者加入一个 polyfill 以保证旧浏览器不会报错。目前引擎并没有添加这些 polyfill,但是我们有计划在 4.0.x 版本中为开发者自动添加 polyfill 支持。
更智能、更严格的 TypeScript 类型推断
白鹭引擎4.0 版本中我们针对 TypeScript 的特性,将引擎 API 进行了更细致的梳理,引入更细致的 API 方法签名,以比较常见的 DisplayObject.addEventListener
这个 API 为例,原来的方法签名为
class DisplayObject {
public addEventListener(type:string,listener:Function,thisObject:any) {
}
}
class Main {
private run() {
var button = new DisplayObject();
button.addEventListener(egret.TouchEvent.TOUCH_TAP,
function(e:egret.TouchEvent) { // 事件类型必须手动声明为 egret.TouchEvent,才能保证严格类型
this.doSomething(); // 第三个参数传递的是 button,函数里的 this 应该是button,不是 Main 的实例,所以不能调用 doSomething() 方法
},button);
);
}
private doSomething(){
}
}
比如在白鹭引擎4.0版本中,DisplayObject 的类型被调整为了以下类型
class DisplayObject {
public addEventListener<Z>(type:"tap",listener:(this:Z,e:egret.TouchEvent),thisObject:Z)
public addEventListener<Z>(type:string,listener:(this:Z,e:egret.Event),thisObject:Z) {
}
}
class Main {
private run() {
var button = new DisplayObject();
button.addEventListener(egret.TouchEvent.TOUCH_TAP,
function(e) { // 事件类型无需手动声明就可保证严格类型
console.log (e.local_x) //由于已经推断出 e 的类型是 egret.TouchEvent,所以这里会报错
this.doSomething(); //自动推断出这里的 this 应该是 button,进而检查出这里会报错
},button);
);
}
private doSomething(){
}
}
允许使用 async / await 关键词
async / await 是 ES2017 语法标准,他可以大幅节省异步代码的处理。注意使用这个语法糖需要在 tsconfig.json
中添加 lib : es6
或者 lib : es2015.promise
可能问题
升级到白鹭引擎4.0之后,您可能会遇到以下问题:
- Egret Wing 代码提示报错。
如果您遇到这种问题是因为您的 IDE 尚不支持 TypeScript 2.1,请把对应的 IDE 升级至最新版本。 Egret Wing 升级至 4.0 以上版本。 - 编译代码报错
升级到 TypeScript 2.1 之后,TypeScript 变得更为智能,也变得更为严格,可能会有一些之前的不规范的写法会导致报错,对其进行调整即可,比如if ( x == false ) {
这样的逻辑在 TypeScript 1.8 不会报错,但是在 2.1 会报错,因为这种代码虽然是可以正确运行,但是有很大的潜在风险(比如 x = 0 )的时候。 - 编译代码出现错误,典型错误堆栈如下:
D:\GitHub\egret-core\tools\lib\typescript-plus\lib\typescript.js:57926
callExpression.arguments.forEach(function (argument) {
^
TypeError: Cannot read property 'forEach' of undefined
at visitCallExpression (D:\GitHub\egret-core\tools\lib\typescript-plus\lib\t
ypescript.js:57926:33)
at visitExpression (D:\GitHub\egret-core\tools\lib\typescript-plus\lib\types
cript.js:57824:17)
at visitStaticMember (D:\GitHub\egret-core\tools\lib\typescript-plus\lib\typ
escript.js:57765:17)
at visitStatement (D:\GitHub\egret-core\tools\lib\typescript-plus\lib\typesc
ript.js:57616:17)
at visitFile (D:\GitHub\egret-core\tools\lib\typescript-plus\lib\typescript.
js:57602:13)
at buildDependencyMap (D:\GitHub\egret-core\tools\lib\typescript-plus\lib\ty
pescript.js:57590:13)
at Object.reorderSourceFiles (D:\GitHub\egret-core\tools\lib\typescript-plus
\lib\typescript.js:57562:9)
at Compiler.sortFiles (D:\GitHub\egret-core\tools\actions\Compiler.js:113:29
)
at Compiler.compileNew (D:\GitHub\egret-core\tools\actions\Compiler.js:101:1
4)
at Compiler.compileGame (D:\GitHub\egret-core\tools\actions\Compiler.js:52:2
5)
这个问题是我们在进行版本升级时考虑不周引发的问题,对此非常抱歉,这个问题已经在下一个版本( 4.0.1 ) 确认会得到解决,您也可以通过尽可能的不要在类的静态属性中直接创建对象来规避这个问题。