[CSDN.NET 张红月/编译] 前段时间,微软发布了语言,这个项目主要的负责人是 Anders Hejlsberg (C#、TurboPascal 之父)。TypeScript提供了类、模块和接口来帮助您构建健壮的组件,它可以帮助 JavaScript开发人员更容易地编写和维护应用程序。这似乎预示着微软正在试图使用TypeScript来替代JavaScript。
在Web领域,几乎每周都会出现新的语言来试图取代JavaScript,比如谷歌推出的就是想解决所有JavaScript不能修复的根本性问题;后来的出现更煽动了这场取代JavaScript的战争。现在,微软也加入了,这不禁让我想知道为什么?
个人偏见
在具体讨论TypeScript之前,我先阐述一下个人感受,你可以在看完后对此进行评论。Web开发行业有个很现实的问题,该行业对JavaScript人才的需求一直在增长,过去10年中,虽然JavaScript的高手越来越多,但仍然是供不应求的。
这种高需求低供给的现状也让优秀的JavaScript开发人员处于令人敬畏的位置,开发人员并不希望改变现状,因为这样他们的薪资就可以得到保障。当然,从个人角度考虑,谁都不愿意改变,但是从整个Web发展来看,肯定希望能有更多优秀人才加入进来,让Web开发行业不断成长,更加美好!
我认为编译为JavaScript的语言很难达到这一目标。我们应该说服更多的人学习JavaScript,而不是提供更多的选择让他们放弃编写JavaScript。我常在想,如果所有的团队、公司都把时间和精力花在研究和探索JavaScript的替代者而非维护、传播它,那将会发生怎样的一番景象。
需要澄清的是,JavaScript并非完美无瑕的语言。话说尺有所短,寸有所长,我使用过的所有语言都有利与弊,JavaScript也不例外。但我希望所有人都能齐心协力地研究一个项目,而不是分裂和互相替代。
什么是TypeScript?
首先,TypeScript是JavaScript的首要超集(TypeScript is first and foremost a superset of JavaScript),TypeScript完全兼容JavaScript语言。除此之外,它还添加了更多的功能,通过TypeScript编译,可以把代码进行转换,使之与ECMAScript 5兼容。这与其他编译为JavaScript的语言是不同的。TypeScript并没有创造新的语法,也就是说JavaScript开发人员很快就可以使用TypeScript开发更多的功能。值得一提的是,TypeScript允许加入注释,让编译器理解所支持的对象和函数,编译器会移除注释,不会增加开销;增加一个完整的类结构,使之更新是传统的面向对象语言。语法借用了原始的JavaScript 2/ECMAScript 4提案,同时也可以作为ActionScript 3实现。
- var myName: string = "Nicholas";
- function add(num1: number, num2: number): number {
- return num1 + num2;
- }
- function capitalize(name: string): string {
- return name.toUpperCase();
- }
如果你使用过Pascal或者Delphi,肯定会对冒号式语法很熟悉,它们都是使用相同的语法来指明类型。JavaScript里面的strings、numbers和booleans在TypeScript里面所呈现的是string、number和bool(备注:都是小写)。这些注释会帮助TypeScript编译器判断所使用的值是否正确。例如下面的这个例子,在页面中会出现警告:
- // warning: add() was defined to accept numbers
- var result = add("a", "b");
由于add()方法是接受numbers类型的,所以在TypeScript编译器中会出现警告。
TypeScript也非常智能,能够在声明时判断数据类型。例如,下面这些都是自动声明类型的:
- var count = 10; // assume ": number"
- var name = "Nicholas"; // assume ": string"
- var found = false; // assume ": bool"
所以你无需声明变量类型,编译器可以自己弄清楚类型信息。
也许这些注释最酷的地方是能够正确注释回调函数。假设数组的每个item里面都会运行一个函数,与Array.prototype.forEach()相似。如果使用JavaScript,你通常会这样定义:
- function doStuffOnItems(array, callback) {
- var i = 0,
- len = array.length;
- while (i < len) {
- callback(array[i], i, array);
- i++;
- }
- }
callback()函数接受3个参数:值、索引和数组本身。你很难在不阅读代码的情况下了解函数的具体信息。而在TypeScript里面,你可以通过注释使函数参数更加详细:
- function doStuffOnItems(array: string[],
- callback: (value: string, i: number, array: string[]) => {}) {
- var i = 0,
- len = array.length;
- while (i < len) {
- callback(array[i], i, array);
- i++;
- }
- }
上面这段代码,对doStuffOnItems()方法里面的参数进行了更加详细的注释。第一个参数是一个字符串类型的数组,第二个参数是一个接受3个参数的函数。备注:上面的双箭头是采用ECMAScript 6语法,编译器可以在执行之前自动验证函数参数匹配。
类型注释算是TypeScript的核心,可以与编译器进行很好的交换。通过注释这些额外的信息,编辑器不仅可以在执行前对类型进行检查,还可以提供更好的智能支持。Visual Studio、Vim、Sublime Text 2和Emacs上都支持TypeScript插件,大家可以去尝试一下!
附加功能
TypeScript加入了静态类型语法,还支持ECMAScript 6的类和模块(正如目前所定义的),意味着你可以编写类似下面的代码:
- class Rectangle {
- constructor(length: number, width: number) {
- this.length = length;
- this.width = width;
- }
- area() {
- return this.length * this.width;
- }
- }
转换成TypeScript后:
- var Rectangle = (function () {
- function Rectangle(length, width) {
- this.length = length;
- this.width = width;
- }
- Rectangle.prototype.area = function () {
- return this.length * this.width;
- };
- return Rectangle;
- })();
注意:上面构造函数没有问题,它是可以放在原型里的。
除了模块和类,TypeScript还支持自定义接口,虽然接口没有按照ECMAScript 6标准去定义,但在涉及到类型检查时还是非常有用的。 由于JavaScript代码常常会定义大量的常量对象,所以,接口提供了一种非常简单的方式来验证对象类型使用的正确与否。例如:
- interface Point {
- x: number;
- y: number;
- }
- function getDistance(pointA: Point, pointB: Point) {
- return Math.sqrt(
- Math.pow(pointB.x - pointA.x, 2) +
- Math.pow(pointB.y - pointA.y, 2)
- );
- }
- var result = getDistance({ x: -2, y: -3}, { x: -4, y: 4})
在上述代码中,定义了一个Point接口,并且包含两个属性:x,y。getDistance()方法接受两个点:pointA和pointB,并且计算两点之间的距离。这两个参数可以是任何包含x,y属性的对象,这意味着TypeScript可以通过检查对象定义来保证对象包含的属性正确。
接口和类都可以注入类型系统来提供更好的错误检查,模块只是把相关功能结合在一起。
喜欢的地方
首先,可以在TypeScript里面编写JavaScript代码,微软并没有完全创造一门新语言,他们试图以更有价值的方式来使用JavaScript语言。另外值得高兴的是把代码预编译成JavaScript,这很有实际意义。对TypeScript生成代码进行调试也不那么困难,因为它使用了大家非常熟悉的模式。
另我印象最深的是TypeScript没有做什么——它没有把类型检查信息输入到JavaScript代码里面,所有的类型注释和错误检查都在开发时完成。除非你是手动使用JavaScript代码,否则最终的代码将不会做任何类型检查。类和模块会在转换成普通的JavaScript代码时完全消失,在最后的JavaScript代码里面是不会出现任何使用过的接口信息。
编辑器集成也相当不错,你只需要在编辑器提示警告或错误时添加一些注释就可以了。能够明确定义回调函数也是令人印象深刻的,这样就可以检验是否有不正确的值传到函数里。
另外值得高兴的是,TypeScript是开源的。微软致力于发展开放的TypeScript社区,持续运转这个开源社区还有待观察,但最起码已经采取措施,保证了这种可能性。
不喜欢的地方
当赞赏微软使用ECMAScript 6类时,我不禁担心它是否会毁掉这门语言。通过与TypeScript项目成员的交谈获知:在类和模块上,他们会保持与ECMAScript 6语法同步。理论上,这样的做法值得称赞,它鼓励人们学习未来会很有用的技术;但从现实角度出发,这样去定位还是比较困难的,因为ECMAScript 6标准还没完成,在规范没有发布之前更无法保证语法不会改变。这样开发TypeScript的团队会处于非常困难的境地:为了保持与时俱进,必须继续更新语法且要保持开发环境的稳定性。
TypeScript小组希望将来的社区将同时围绕语言和工具发展,及时获知未来的走向。但这也是一把双刃剑,如果他们成功了,将会创建一个庞大的TypeScript社区,但也有可能会因为维护和更新的成本而偏离ECMAScript标准。
我非常不喜欢原始类型布尔型命名为bool,我希望能改成boolean类型,以便映射typeof的返回值,还有string和number类型也一样。
你应该使用它吗?
我认为,TypeScript虽然很有保证,但请记住:目前提供的只是早期的预览版本,TypeScript并不像它的网站看起来那样精美,最终版本可能会在一年后ECMAScript 6发布会确定,现在的版本只是个开发之预览版。
所以,现在真的就值得使用了吗?现在去体验并且把感受反馈给TypeScript团队是不错的做法。如果想把它作为日常工作来使用,这样会存在很大风险。我强烈建议你使用类型注释和接口,因为这些都是完全编译后的代码,并且与ECMAScript 6之间没有直接关系。但要注意避免使用目前ECMAScript 5尚不支持的任何东西。
结论
TypeScript提供了一些与其他编译成JavaScript语言不同的方案,并且添加了一些功能。我很高兴可以在TypeScript中编写JavaScript,并且可以从TypeScript中改善类型检查。这还意味着编写TypeScript代码能够帮助你学习JavaScript。毫无疑问,当编译器集成时,这些类型注释会创建更好的开发体验。一旦ECMAScript 6定案,肯定会有许多开发者开始使用TypeScript,也可以在并不原生支持它的浏览器中编写ECMAScript 6代码。TypeScript仍然有很长的路要走,但还是值得关注的。
作者简介:
Nicholas C.Zakas,雅虎首页的主要开发者之一,也是雅虎用户界面库(YUI)代码贡献者,擅长利用JavaScript、HTML、CSS、XML、XSLT设计和实现WEB界面,他著有《高性能JavaScript》、《JavaScript高级程序设计》(《Professional JavaScript for Web Developers》)等多部JavaScript经典书籍。
原文:
译文: