我用 TypeScript 语言的七个月

388 查看

【感谢@Little2Mao 的热心翻译。如果其他朋友也有不错的原创或译文,可以尝试推荐给伯乐在线。】

从2012年12月开始,我用 TypeScript 作为主要语言,用于一个大规模的企业项目。项目下个月要发布了,我想分享一些细节内容,包括我们团队怎么使用 TypeScript 的,还有成就项目的工作流程。

 

什么是TypeScript

TypeScript是由微软开发的一个能够在Node.js上运行的开源语言和编译器。这个语言是在ECMAScript6基础上演化并吸收了生成Javascript类别和接口的一些特性。Typescript 的编译器使用TypeScript语言编写,并且能够在任何兼容Javascript的程序内运行,同时它也是作为node.js的一个工具包发布的。所以该语言最终生成的仍然是Javascript脚本。

 

评估

在2012年十一月期间,我们发现我们所选择的开发工具和对于Typescript的试用确实给团队带来很多便利。起初,我们试用了Haxe,Dart,Coffescript等一系列语言,但是我们最终还是被拥有ECMAScript6特性Javascript编译器:Tyepscript打动了。我们所期望的是使用Javascript作为开发语言但同时又想要在我们的开发过程中注入一定的结构框架,而且希望能够依靠编辑器来进行一些纠错和验证。所以实际上我们最终还是只有在Javascript和Typescript之间作选择。在这基础上,团队作了几个小型的项目雏形,并且迅速发现了以下一些有趣的特性:

验证:Typescript能够在编译的同时让我们验证一些代码在不同模块中的重复使用。在声明变量类型和定义语句方法的时候,我们能够很有效的对所有call/get/set的使用在所有模块中进行交叉验证。如果一个属性被赋给了bbox.controls.image类,那么在编译时只有图片实例或其子类才能够满足编译条件。

报错:Typescript编译器能够提供非常细节的报错,如果提供额外的类和接口信息,那报错的内容会更加的详细。

轻量化:Typescript的类和接口在编译时会蒸发的一干二净从而生成纯净的Javascript脚本。

ECMAS6(ES6):Typescript在ES6的基础上添加了类和接口。它让我们能够利用最新的Javascript语法规则去编写程序同时在编译时添加ES3,ES5的标签,使得其能够兼容ES3,ES5的标准。这让代码的整理变得非常轻松。

Build process:在我们最初的检验和测试过程中,有一个部分是利用Ant创建一个团队进程。通过对环境的适当调试,开发者能够和SCM(架构部署)进行同步并且建立一个拥有所有代码组件(codepakages)的本地服务器用于开发和调试。整个创建的过程迁入了LESS,RequireJS,Uglify2,TypeScript,模板处理和服务器的生成。

 

使用

在评估之后的几个月里,我们基于TypeScript建立了一个稳定的团队工作流程并且从中获利良多。进程的创建(buildprocess)是我们开发过程中一个至关重要并且每天都会使用到的一个过程。基于TypeScript,我们每天的工作流程基本上如下所述:

  • 从SCM进行更新
  • 运行‘antall’==>创建全部+运行本地服务器
  • 运行’antdev’或者’antts’==>增量式创建
  • 检校创建过程中的错误或者在浏览器中进行测试
  • 清理bug然后重复以上步骤

我个人非常喜欢这样的运作模型,从中我发现我们花在浏览器测试阶段的时间远少于之前的JavaScript项目。由于Build过程中就已经检校了一些接口/类型/语法的错误,因此在浏览器测试阶段我们就减少了对此类错误的勘误工作量。一旦所有人都熟悉了TypeScript的debugging流程,我们大大的提高了工作效率,这是在以前的开发过程中所没有体验过的。花了5秒钟编译但是最终却删除了整一个没有运作的毫无意义类听起来有点不能接受。这种防患于未然的debugging方式节省我们大约2个月的时间,而且代码的质量也大大提高了。

当初在我们进行开发的时候,TypeScript定义文件的质量和内容不是非常理想。定义文件能够让你非常安全的从外部定义JavaScript的接口类型,但这样做你的代码必须在编译时完全遵照定义文件。自从这个项目开始之际,我们借DefinitelyTyped项目为一些主要的或者非主要的JavaScript库编写润饰了180个定义。小组最后在创建进程时使用了关于Require,JQuery,Backbone,Bootstrap,Underscore和EaselJS的定义文件。现在为TypeScript添加定义文件,你只要在你的main.ts文件中添加一下的代码就可以了。

根据同样的方法你也可以向TypeScript中添加一些外部库。某种程度上来说定义文件,接口和TypeScript的类的运作方式是类似的。为了简化我们创建进程的过程,我们将这些调用过程全部综合到一个init.ts文件中,这样当编译器工作的时候就可以自动载入所有该应用所需要TypeScript代码。哪怕是那些本需要通过先调用模块才能调用的类也能在这里被调用表达,这样这些类就会在编译时预先在外部生成一个模块文件以供使用。注意这个外部模块的代码中”exportClass”的语法,它会告诉编译器将文件视为一个外部模块进行调用,而编译器标识”-moduleamd”会使得编译器将模块编排成AMD或者CommonJS的格式

除此之外,TypeScript还有另外一个很优雅整合代码的功能。每一个类和变量都被输出到浏览器窗口实体之外的一个路径里以供全局访问。我们使用了bbox作为所有类和变量的命名空间,同时提供了输入时的支持,你也可以便捷的为你自己的应用建立一个良好命名空间。以上的模块包含在了”bbox.controls”里并且在运行时可以发现它被输出到了bbox.controls,Bounds中。考虑到我们有用到大约60多个类,我们最大化的使用了这个模块系统并且在开发过程中使用的非常顺利。你可以遵照这个方法自由的导出和类别化你自己的变量或者所有的类,而不需要让所有的变量都归属于某个类。由于提供了类别和权限的限制,类别化输出的变量对于模块内单一的变量非常适用。随着类别和模块的介入,你使用JavaScript的方式也会有所改变,并且很难形成比较差的实践方式。随着一个能够监测到通过数组或者一个很特殊的类别重写了某实体的高级编译器,你可以一不同的方式利用JavaScript进行开发,TypeScript作为一种语言有着它独特的工作模式。它已经不完全是JavaScript了,但全包含了JavaScript原有的所有特性。

通过一系列的开发实践我发祥我自己已经通过对代码的重构实现了开发策略的转换。由于有时需检查在不同部分受到修改影响的代码,我开始在有意识的改变变量类别,接口和命名空间等方面相信编译器本身的行为。在编译之后我才会修改结果,并且根据需要进行代码的重构。这在很多方面都使我能够很有效处理较大的代码量。编译器为我省去了很多debugging的负担。

至于我的开发环境,尽管其他团对成员选择了Jetbrians,我依然选择了sublimetext2+TypeScirpt语法高亮。毫无异议,我发觉即使没有自动完成的功能,sublime依然能提供很好的TypeScript开发环境。由于TypeScript编译器本身就有着增量式的编译功能和丰富的IDE整合功能,可能需要更多的时间来证明到底Sublime/Edge/Jetbrains哪一个才是最适合的开发工具。

最后,当我爱上使用TypeScript的同时(当然,我也会继续用下去),我发现了一个令人望而生畏的地方。有很多次,当你一头扎进编译环境中,编译器却由于输入信息不可用而阻止你调用一个方法或者变量。每当这时,我们发现只有我们手动修复bug时,利用关联数组语法(associativearraysyntax)去解决这个问题。比如:无论什么样的分类形式,foo[‘myProperty’]foo[‘myMethod’]() 应该能够让你介入foo的myProperty和myMethod属性。这看起来有一些不可思议,但只要记住随时可能用到关联数组语法(associativearraysyntax)就万事大吉了,你总有需要它的地方。

最后附上一些项目开发过程中的总结数据:

  • 63个typescript类
  • 12个运行库(libs)(Underscore,Require,Bootstrap,Jquery,Backbone,EaselJS…)
  • 一次创建所有进程,用时8秒
  • 一次创建所有开发进程,用时5秒
  • 149Kb大小的运行库文件和411Kb大小的类文件

总结

在过去7个月里用TypeScript做开发是一件非常愉快的事情。在之前的开发经验里,我使用过ActionScript/ES4,但由于有着相似的结构,我很快就适应了TypeScript,同时保持了JavaScript 优雅的代码便捷性。在很多方面,我发现对于TypeScript的使用,的确使我们在团队代码质量和截止日期上有了很大提升。我不认为我是微软的死忠,但是TypeScript确实使我眼前一亮。它是过去三年里我所接触的最好的也是比较容易接受的一个网页开发的工具。我期待在未来能够在更多的项目中用到,并且能够参与到该语言/编译器的开发中去。

这周我将会在旧金山的Build去了解TypeScript0.9的一些特性,下个月我会在Senchacon360Stack

我爱TypeScript!

Ted