什么是TypeScript,为什么我要用它来代替JavaScript?

你能描述一下TypeScript语言是什么吗?

它能做什么JavaScript或可用库不能做的事情,这会让我有理由考虑它?

642793 次浏览

我最初写这个答案时TypeScript还在五年后,这是一个不错的概述,但看在下面的Lodewijk的回答中查看更多深度

1000英尺视野…

TypeScript是JavaScript的超集,主要提供可选的静态类型、类和接口。最大的好处之一是使IDE能够提供更丰富的环境来发现常见错误当你键入代码时

要了解我的意思,请查看语言上的微软的介绍视频

对于大型JavaScript项目,采用TypeScript可能会产生更健壮的软件,同时仍然可以部署在运行常规JavaScript应用程序的地方。

它是开源的,但如果您使用受支持的IDE,您只能在键入时获得聪明的智能感知。最初,这只是微软的Visual Studio(也在migueldeicaza的博客文章中提到)。这些天,其他IDE也提供TypeScript支持

还有其他类似的技术吗?

还有脚本编写,但这确实有不同的目的。恕我直言,CoffeeScript为人类提供了易读性,但TypeScript也通过其可选的静态类型为工具提供了深度易读性(请参阅此最近的博客文章以获得更多批评)。还有Dart,但这是JavaScript的完整替代品(尽管它可以生成JavaScript代码

示例

例如,这里有一些TypeScript(您可以在TypeScript Playground中使用它)

class Greeter {greeting: string;constructor (message: string) {this.greeting = message;}greet() {return "Hello, " + this.greeting;}}

这是它将生成的JavaScript

var Greeter = (function () {function Greeter(message) {this.greeting = message;}Greeter.prototype.greet = function () {return "Hello, " + this.greeting;};return Greeter;})();

请注意TypeScript如何定义成员变量和类方法参数的类型。这在转换为JavaScript时被删除,但被IDE和编译器用于发现错误,例如将数字类型传递给构造函数。

它还能够推断未显式声明的类型,例如,它将确定greet()方法返回一个字符串。

调试TypeScript

许多浏览器和IDE通过源代码映射提供直接调试支持。有关更多详细信息,请参阅此Stack Overflow问题:使用Visual Studio调试TypeScript代码

想了解更多?

我最初写这个答案时TypeScript还在印刷中。查看这个问题的Lodewijk的回答以获取更多最新细节。

TypeScript基础知识”-Dan Wahlin约翰·帕帕的Pluralsight视频课程非常好,目前(2016年3月25日)更新以反映TypeScript 1.8,TypeScript简介。

对我来说,除了智能感知的可能性之外,真正好的功能是接口模块,实现AMD的易用性,以及在使用IE调用时使用Visual Studio TypeScript调试器的可能性。

总结一下:如果按预期使用,TypeScript可以使JavaScript编程更可靠、更容易。它可以在完整的SDLC上显着提高JavaScript程序员的生产力。

TypeScript与JavaScript的关系

TypeScript是JavaScript的类型化超集,可编译为纯JavaScript-typescriptlang.org.

JavaScript是由ECMA技术委员会39开发的编程语言,ECMA技术委员会39是由许多不同的利益相关者组成的一群人。TC39是由ECMA主持的委员会:一个内部标准组织。JavaScript有许多不同的实现,由许多不同的供应商(例如谷歌、微软、甲骨文等)。JavaScript的目标是成为网络的通用语言。

TypeScript是JavaScript语言的超集,它有一个开源编译器,主要由一个供应商开发:Microsoft。TypeScript的目标是帮助通过类型系统及早发现错误,并使JavaScript开发更高效。

从本质上讲,TypeScript通过三种方式实现其目标:

  1. 支持现代JavaScript功能-JavaScript语言(不是运行时)通过ECMAScript标准标准化。并非所有浏览器和JavaScript运行时都支持所有ECMAScript标准的所有功能(请参阅此概述)。TypeScript允许使用许多最新的ECMAScript功能并将它们转换为您选择的旧ECMAScript目标(请参阅--target编译器选项下的编制目标列表)。这意味着您可以安全地使用新功能,如模块、lambda函数、类、扩展运算符和解构,同时保持向后兼容旧浏览器和JavaScript运行时。

  2. 高级类型系统-类型支持不是ECMAScript标准的一部分,并且可能永远不会由于JavaScript的解释性质而不是编译性质。TypeScript的类型系统非常丰富,包括:接口、枚举、混合类型、泛型、联合/交叉类型、访问修饰符等等。TypeScript的官网链接概述了这些特性。TypeScript的类型系统与大多数其他类型语言相当,在某些情况下可以说是更强大。

  3. 开发人员工具支持-TypeScript的编译器可以作为后台进程运行,以支持增量编译和IDE集成,这样您就可以更轻松地导航、识别问题、检查可能性和重构代码库。

TypeScript与其他JavaScript目标语言的关系

与其他编译为JavaScript的语言相比,TypeScript有着独特的哲学。JavaScript代码是有效的TypeScript代码;TypeScript是JavaScript的超集。您几乎可以将.js文件重命名为.ts文件并开始使用TypeScript(请参阅下面的“JavaScript互操作性”)。TypeScript文件被编译为可读的JavaScript,因此可以迁移回来,并且理解编译后的TypeScript一点也不难。TypeScript建立在JavaScript的成功之上,同时改进其弱点。

一方面,你有未来的证明工具,它们采用现代ECMAScript标准,并将其编译成更旧的JavaScript版本,Babel是最受欢迎的版本。另一方面,你有一些语言可能与针对JavaScript的JavaScript完全不同,比如CoffeeScript、Clojure、Dart、Elm、Haxe、Scala.js,还有更多的主机(参见这个列表)。这些语言,尽管它们可能比JavaScript的未来更好,但它们的未来更有可能没有得到足够的采用来保证它们的未来。你可能也很难找到有经验的开发人员来使用其中一些语言,尽管你会发现他们通常会更热情。与JavaScript的互操作性也可能涉及更多,因为它们与JavaScript的实际内容相距甚远。

TypeScript位于这两个极端之间,从而平衡了风险。无论以任何标准来看,TypeScript都不是一个冒险的选择。如果您熟悉JavaScript,则只需很少的努力就可以习惯,因为它不是完全不同的语言,具有出色的JavaScript互操作性支持,并且最近已被大量采用。

可选的静态类型和类型推断

JavaScript是动态类型的。这意味着JavaScript在运行时实际实例化变量之前不知道变量是什么类型。这也意味着可能为时已晚。TypeScript为JavaScript添加了类型支持,并在编译为JavaScript时捕获类型错误。如果你玩得好(你输入代码的严格程度或你输入代码的严格程度取决于你),由某些变量是某种类型的错误假设引起的错误可以完全根除。

TypeScript通过类型推断的使用使键入变得更容易并且不那么显式。例如:TypeScript中的var x = "hello"var x : string = "hello"相同。类型只是从其使用中推断出来的。即使你没有显式键入类型,它们仍然存在,以避免你做一些否则会导致运行时错误的事情。

默认情况下,TypeScript是可选类型的。例如,function divideByTwo(x) { return x / 2 }是TypeScript中的一个有效函数,可以使用任何类型的参数调用,即使使用字符串调用它显然会导致运行时错误。就像你在JavaScript中习惯的那样。这很有效,因为当没有显式分配类型并且无法推断类型时,就像在dideByTwo示例中一样,TypeScript将隐式分配类型any。这意味着dideByTwo函数的类型签名自动变为function divideByTwo(x : any) : any。有一个编译器标志禁止这种行为:--noImplicitAny。启用此标志可以提高安全性,但也意味着你将不得不进行更多的键入。

类型有相关的成本。首先,有一个学习曲线,其次,当然,使用适当的严格类型设置代码库也会花费你更多的时间。根据我的经验,这些成本对于任何与他人共享的严肃代码库都是完全值得的。Github中编程语言和代码质量的大规模研究表明“一般来说,静态类型语言比动态类型更不容易出现缺陷,并且在同一方面,强类型比弱类型更好”。

有趣的是,这篇论文发现TypeScript比JavaScript更不容易出错:

对于那些具有正系数的人,我们可以期望语言在其他条件不变的情况下,与更多的缺陷修复相关。这些语言包括C、C++、javascript、Objective-C、Php和Python。语言Clojure、Haskell、Ruby、Scala和TypeScript,都有负系数,意味着这些语言可能比平均水平更容易导致缺陷修复提交。

增强的IDE支持

与JavaScript相比,TypeScript的开发体验有了很大的改进。TypeScript编译器会实时通知IDE其丰富的类型信息。这带来了几个主要的优势。例如,使用TypeScript,你可以安全地在整个代码库中进行重构,如重命名。通过代码完成,你可以获得有关库可能提供的任何函数的内联帮助。不再需要记住它们或在在线参考资料中查找它们。当你忙于编码时,编译错误会直接在IDE中以红色弯曲线报告。总而言之,与使用JavaScript相比,这可以显着提高生产力。人们可以花更多的时间编码,更少的时间调试。

有很多IDE对TypeScript有很好的支持,比如Visual Studio Code、WebStorm、Atom和Sublime。

严格的零检查

形式为cannot read property 'x' of undefinedundefined is not a function的运行时错误通常是由JavaScript代码中的错误引起的。开箱即用的TypeScript已经降低了发生此类错误的可能性,因为不能使用TypeScript编译器不知道的变量(any类型变量的属性除外)。尽管仍然有可能错误地使用设置为undefined的变量。然而,在TypeScript的2.0版本中,你可以通过使用不可为空的类型来消除这些类型的错误。这工作如下:

启用了严格的空检查(--strictNullChecks编译器标志),TypeScript编译器不允许将undefined分配给变量,除非您显式声明它是可空类型。例如,let x : number = undefined将导致编译错误。这完全符合类型理论,因为undefined不是数字。可以将x定义为number的和类型,并将undefined定义为纠正这一点:let x : number | undefined = undefined

一旦知道一个类型是可空的,这意味着它的值也可以是nullundefined,TypeScript编译器就可以通过基于控制流的类型分析来确定你的代码是否可以安全地使用一个变量。换句话说,当你通过例如if语句检查一个变量是undefined时,TypeScript编译器会推断你代码控制流该分支中的类型不再可以为空,因此可以安全地使用。这是一个简单的例子:

let x: number | undefined;if (x !== undefined) x += 1; // this line will compile, because x is checked.x += 1; // this line will fail compilation, because x might be undefined.

在构建过程中,TypeScript的2016年会议联合设计师Anders Hejlsberg详细解释和演示了此功能:视频(从44:30到56:30)。

汇编

要使用TypeScript,您需要一个构建过程来编译为JavaScript代码。构建过程通常只需要几秒钟,当然这取决于您的项目的大小。TypeScript编译器支持增量编译(--watch编译器标志),以便可以更快地编译所有后续更改。

TypeScript编译器可以在生成的. js文件中内联源映射信息,也可以创建单独的. map文件。源代码映射信息可以被调试工具(如ChromeDevTools和其他IDE)使用,将JavaScript中的行与在TypeScript中生成它们的行联系起来。这使得您可以直接在TypeScript代码上设置断点并在运行时检查变量。源代码映射信息工作得很好,早在TypeScript出现之前就已经存在了,但是调试TypeScript通常不如直接使用JavaScript时那么好。以this关键字为例。由于自ES2015以来围绕闭包的this关键字的语义学发生了变化,this实际上可能在运行时作为名为_this的变量存在(参见这个答案)。这可能会在调试期间使您感到困惑,但如果您了解它或检查JavaScript代码,通常不会成为问题。应该注意的是,Babel也存在完全相同的问题。

TypeScript编译器还可以做一些其他的技巧,比如基于装饰者生成拦截代码、为不同的模块系统生成模块加载代码和解析JSX。然而,除了TypeScript编译器之外,你可能还需要一个构建工具。例如,如果你想压缩你的代码,你必须在你的构建过程中添加其他工具来做到这一点。

有一些TypeScript编译插件可用于webpackGulpGrunt以及几乎任何其他JavaScript构建工具。TypeScript留档有一个关于与构建工具集成的部分,涵盖了所有这些。如果您想进行更多的构建时间检查,也可以使用linter。还有大量的种子项目可以让您开始使用TypeScript以及一系列其他技术,如Angular 2、React、Ember、SystemJS、Webpack、Gulp等。

JavaScript互操作性

由于TypeScript与JavaScript密切相关,它具有强大的互操作性功能,但是需要一些额外的工作来使用TypeScript中的JavaScript库。需要TypeScript定义,以便TypeScript编译器理解_.groupByangular.copy$.fadeOut等函数调用实际上并不是非法语句。这些函数的定义放在.d.ts文件中。

定义可以采取的最简单形式是允许以任何方式使用标识符。例如,当使用Lodash时,单行定义文件declare var _ : any将允许您在_上调用您想要的任何函数,但是,当然,您仍然可以犯错误:_.foobar()将是合法的TypeScript调用,但当然,在运行时是非法调用。如果您想要适当的类型支持和代码完成,您的定义文件需要更准确(参见土豆泥定义的示例)。

预打包有自己类型定义的npm模块会被TypeScript编译器自动理解(参见留档)。对于几乎任何其他不包含自己定义的半流行JavaScript库,有人已经通过另一个npm模块提供了类型定义。这些模块以“@type/”为前缀,来自名为定义类型的Github存储库。

有一个警告:类型定义必须与您在运行时使用的库的版本匹配。如果不匹配,TypeScript可能会禁止您调用函数或取消引用存在的变量,或允许您调用函数或取消引用不存在的变量,仅仅是因为类型与编译时的运行时不匹配。因此,请确保为您使用的库的正确版本加载正确版本的类型定义。

老实说,这有点麻烦,这可能是你不选择TypeScript的原因之一,而是选择像Babel这样的东西,它根本不需要得到类型定义。另一方面,如果你知道你在做什么,你可以很容易地克服任何由不正确或丢失定义文件引起的问题。

从JavaScript转换为TypeScript

任何.js文件都可以重命名为.ts文件,并通过TypeScript编译器运行,以获得语法上与输出相同的JavaScript代码(如果它首先在语法上是正确的)。即使TypeScript编译器收到编译错误,它仍然会生成.js文件。它甚至可以接受.js文件作为带有--allowJs标志的输入。这允许您立即开始使用TypeScript。不幸的是,编译错误可能会在开始时发生。需要记住的是,这些不是您可能习惯于其他编译器的显示停止错误。

由于TypeScript的本质,在将JavaScript项目转换为TypeScript项目时,一开始就会出现编译错误是不可避免的。TypeScript检查所有代码的有效性,因此它需要知道所有使用的函数和变量。因此,所有这些代码都需要有类型定义,否则肯定会发生编译错误。正如上面一章中提到的,对于几乎任何JavaScript框架,都有.d.ts的文件可以通过安装包类型轻松获取。然而,可能是你使用了一些没有TypeScript定义的不起眼的库,或者你使用了一些JavaScript原语。在这种情况下,您必须为这些位提供类型定义以使编译错误消失。只需创建一个.d.ts文件并将其包含在tsconfig.json的files数组中,以便TypeScript编译器始终考虑它。在它中声明那些TypeScript不知道的位为类型any。一旦您消除了所有错误,您就可以根据您的需要逐步将键入引入这些部分。

为了将TypeScript引入构建管道,还需要进行一些(重新)配置构建管道的工作。正如在编译一章中提到的,那里有很多很好的资源,我鼓励你寻找使用你想要使用的工具组合的种子项目。

最大的障碍是学习曲线。我鼓励你一开始就尝试一个小项目。看看它是如何工作的,它是如何构建的,它使用了哪些文件,它是如何配置的,它在你的IDE中是如何运行的,它是如何结构化的,它使用了哪些工具,等等。当你知道自己在做什么的时候,将一个大型的JavaScript代码库转换为TypeScript是可行的。例如,阅读这个博客在72小时内将600k行转换为打字稿)。在跳转之前,请确保你很好地掌握了这门语言。

收养

TypeScript是开源的(Apache 2许可,见github),并得到Microsoft的支持。Anders Hejlsberg,C#的首席架构师是该项目的带头人。这是一个非常活跃的项目;TypeScript团队在过去几年中发布了许多新功能,许多伟大的功能仍在计划中(见路线图)。

关于采用和普及的一些事实:

TypeScript的作用类似于less或sass对CSS的作用。它们是它的超级集,这意味着你编写的每个JS代码都是有效的TypeScript代码。此外,你可以使用它添加到语言中的其他好东西,转换后的代码将是有效的js。你甚至可以设置你想要生成代码的JS版本。

目前TypeScript是ES2015的超级集,因此开始学习新的js功能并转译为项目所需的标准可能是一个不错的选择。

Ecma脚本5(ES5),所有浏览器都支持和预编译。ES6/ES2015和ES/2016今年有很多变化,所以要弹出这些变化,中间有一些应该关心的东西,所以TypeScript。

TypeScript是Types->意味着我们必须定义每个属性和方法的数据类型。如果你知道C#,那么TypeScript很容易理解。

TypeScript的一大优势是我们在投入生产之前及早发现了与类型相关的问题。如果有任何类型不匹配,这允许单元测试失败。