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

能否请您介绍一下TypeScript语言是什么?

它能做哪些JavaScript或现有库不能做的事情,让我有理由考虑它?

解决办法

我最初写这个答案时,Typescript还在 热销的时候写的。五年后的今天,这是个不错的概述,但请看 但请看下面的Lodewijk'的答案,以了解更多深度。

1000ft view...

[TypeScript][1]是JavaScript的超集,主要提供可选的静态类型、类和接口。其中一个很大的好处是使IDE能够提供一个更丰富的环境,在你输入代码时*发现常见的错误。

要想了解我的意思,请观看Microsoft'的介绍性视频,了解该语言。

对于一个大型的JavaScript项目来说,采用TypeScript可能会带来更强大的软件,同时仍然可以在普通JavaScript应用程序运行的地方进行部署。

它是开源的,但只有当你使用支持的IDE时,你才能在输入时得到聪明的Intellisense。最初,这只是微软的Visual Studio(在Miguel de Icaza的博文中也提到)。如今,其他IDE也提供TypeScript支持

还有其他类似的技术吗?

有[CoffeeScript][5],但这确实是一个不同的目的。我认为,CoffeeScript为人类提供了可读性,但TypeScript也通过其可选的静态类型为*工具提供了深入的可读性(见这篇[最近的博文][6],以了解更多的评论)。还有[Dart][7],但这是对JavaScript的完全替代(尽管它[可以产生JavaScript代码][8])。

例子

作为一个例子,这里有一些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

/h2> 许多浏览器和IDE通过源码图提供直接的调试支持。更多细节请见Stack Overflow的这个问题。用Visual Studio调试TypeScript代码

想了解更多?

我最初写这个答案时,Typescript还在热火朝天地进行着。请看[Lodewijk'的回答][11],以了解更多的最新细节。
评论(28)

TypeScript'与JavaScript的关系

TypeScript是一个类型化的JavaScript超集,可以编译成普通的 JavaScript - typescriptlang.org. JavaScript是一种编程语言,由EMCA'的技术委员会39开发,这是一个由许多不同的利益相关者组成的团体。TC39是一个由ECMA主持的委员会:一个内部标准组织。JavaScript有许多不同的供应商(例如Google、Microsoft、Oracle等)的不同实现。JavaScript的目标是成为网络的通用语言。 TypeScript是JavaScript语言的一个超集,它有一个单一的开源编译器,主要由一个供应商开发。微软。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添加了类型支持。如果你打好你的牌(你的代码类型有多严格,或者你是否打好你的代码,这取决于你),那些由于错误地假设某些变量是某种类型而造成的错误可以完全被根除。 TypeScript通过使用类型推理,使打字变得更容易,更不明确。例如:var x = "hello"在TypeScript中与var x : string = "hello"相同。类型只是从它的使用中推断出来的。即使你没有明确的类型,它们仍然存在,以拯救你的行为,否则会导致运行时错误。 TypeScript在默认情况下是可以选择类型的。例如,"function divideByTwo(x) { return x / 2 }"在TypeScript中是一个有效的函数,可以用任何种参数来调用,尽管用字符串调用它显然会导致运行时错误。就像你在JavaScript中习惯的那样。这样做的原因是,当没有明确指定类型,并且无法推断类型时,就像divideByTwo的例子一样,TypeScript将隐含地指定any类型。这意味着divideByTwo函数的类型签名自动成为function divideByTwo(x : any) : any。 有一个编译器标志可以禁止这种行为:--noImplicitAny。启用这个标志可以给你更大程度的安全,但也意味着你必须做更多的输入工作。 类型有其相关的成本。首先,有一个学习曲线,其次,当然,你将花费更多的时间来建立一个使用适当严格类型的代码库。根据我的经验,在你与他人共享的任何严肃的代码库中,这些成本是完全值得的。Github中关于编程语言和代码质量的大规模研究表明,"静态类型的语言,一般来说,比动态类型的语言更不容易出现缺陷,而且在同样的方面,强类型比弱类型更好"。 有趣的是,这篇论文还发现,TypeScript的错误率比JavaScript低。 对于那些有正系数的语言,我们可以预期,该语言 在其他方面,与更多的缺陷修复有关。 这些语言包括C、C++、JavaScript、Objective-C、Php、和 Python。Clojure、Haskell、Ruby、Scala和TypeScript等语言。 都有负的系数,意味着这些语言的 导致缺陷修复提交的可能性比平均水平低。

增强IDE支持

与JavaScript相比,TypeScript的开发体验有了很大的改进。IDE可以通过TypeScript编译器实时了解其丰富的类型信息。这带来了一些主要的优势。例如,使用TypeScript,你可以在整个代码库中安全地进行重构,如重命名。通过代码完成,你可以获得库中可能提供的任何功能的内联帮助。不再需要记住它们或在在线参考中查找它们。在你忙于编码的时候,编译错误会直接在IDE中以红色的斜线报告。总而言之,与使用JavaScript的工作相比,这使得生产力有了显著的提高。人们可以花更多的时间编码,更少的时间进行调试。 有各种各样的IDE对TypeScript有很好的支持,比如Visual Studio Code、WebStorm、Atom和Sublime。

严格的空值检查

运行时错误的形式是 "无法读取undefined的属性'x' "或 "undefined不是一个函数",这通常是由JavaScript代码中的错误引起的。开箱即用的TypeScript已经降低了这类错误发生的概率,因为我们不能使用TypeScript编译器不知道的变量(除了 "任何 "类型变量的属性)。但是,仍然有可能错误地使用一个被设置为 "未定义 "的变量。然而,在2.0版本的TypeScript中,你可以通过使用非空类型来消除这些错误。其工作原理如下。 启用了严格的空值检查(--strictNullChecks编译器标志),TypeScript编译器将不允许undefined被分配给一个变量,除非你明确声明它是可空类型。例如,let x : number = undefined将导致一个编译错误。这完全符合类型理论,因为undefined不是一个数字。我们可以将x定义为numberundefined的总和类型来纠正这个问题。let x : number | undefined = undefined。 一旦一个类型被知道是nullable,意味着它的类型也可以是nullundefined的值,TypeScript编译器可以通过基于控制流的类型分析确定你的代码是否可以安全地使用一个变量。换句话说,当你通过 "if "语句检查一个变量是 "undefined "时,TypeScript编译器将推断出,在你的代码的控制流分支中,该类型不再是nullable,因此可以安全使用。下面是一个简单的例子。

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.

在构建期间,2016年会议上TypeScript的联合设计者Anders Hejlsberg对这一功能进行了详细的解释和演示。视频 (从44:30到56:30)。

编译

要使用TypeScript,你需要一个构建过程来编译成JavaScript代码。构建过程一般只需要几秒钟,当然,这取决于你的项目的大小。TypeScript编译器支持增量编译(--watch编译器标志),这样所有的后续修改都可以以更快的速度编译。 TypeScript编译器可以在生成的.js文件中内联源码图信息或创建单独的.map文件。源码图信息可以被调试工具使用,如Chrome DevTools和其他IDE's,将JavaScript中的行与TypeScript中生成的行联系起来。这使得你可以在运行期间直接在TypeScript代码上设置断点和检查变量。源码图信息工作得很好,它在TypeScript之前就已经存在了,但是调试TypeScript通常没有直接使用JavaScript时那么好。以this关键字为例。由于自ES2015以来,围绕闭包的this关键字的语义发生了变化,this实际上在运行时可能作为一个叫做_this的变量存在(见本回答)。在调试过程中,这可能会使你感到困惑,但如果你知道这一点或检查JavaScript代码,一般不会有问题。需要注意的是,Babel也有完全相同的问题。 TypeScript编译器还可以做一些其他的技巧,比如基于装饰器生成拦截代码,为不同的模块系统生成模块加载代码,以及解析JXX。然而,除了Typescript编译器之外,你很可能还需要一个构建工具。例如,如果你想压缩你的代码,你将不得不在构建过程中添加其他工具来实现。 在WebpackGulpGrunt和其他几乎所有的JavaScript构建工具中都有TypeScript编译插件。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调用,但在运行时当然是一个非法调用。如果你想要正确的类型支持和代码完成,你的定义文件需要更加精确(见lodash定义的例子)。 Npm模块 预先打包了自己的类型定义的模块会被TypeScript编译器自动理解(见文档)。对于几乎所有其他不包括自己定义的半流行的JavaScript库,有人已经通过另一个npm模块提供了类型定义。这些模块的前缀是"@types/",来自一个叫做DefinitelyTyped的Github资源库。 有一个注意事项:类型定义必须符合你在运行时使用的库的版本。如果它们不匹配,TypeScript可能会不允许你调用一个存在的函数或解除对一个变量的引用,或者允许你调用一个不存在的函数或解除对一个变量的引用,仅仅是因为类型在编译时与运行时不符。所以要确保你为你所使用的库的正确版本加载正确的类型定义。 说实话,这有一点麻烦,这可能是你不选择TypeScript的原因之一,而是去选择像Babel这样的东西,因为它根本不受必须获得类型定义的影响。另一方面,如果你知道你在做什么,你可以很容易地克服由不正确或丢失定义文件引起的任何类型的问题。

从JavaScript转换到TypeScript

任何.js文件都可以被重命名为.ts文件,并通过TypeScript编译器运行,得到语法相同的JavaScript代码作为输出(如果它首先在语法上是正确的)。即使TypeScript编译器出现编译错误,它仍然会产生一个.js文件。它甚至可以用--allowJs标志接受.js文件作为输入。这使你可以立即开始使用TypeScript。不幸的是,在开始时可能会出现编译错误。我们需要记住,这些错误并不像你在其他编译器中可能会遇到的那样,会让你感到震惊。
在将JavaScript项目转换为TypeScript项目时,一开始就会出现编译错误,这是TypeScript的本质所决定的,是无法避免的。TypeScript检查所有代码的有效性,因此它需要知道所有使用的函数和变量。因此,所有的类型定义都需要到位,否则必然会发生编译错误。正如上面一章所提到的,对于几乎所有的JavaScript框架都有.d.ts文件,可以通过安装DefinitelyTyped包轻松获得。然而,你可能使用了一些晦涩难懂的库,而这些库没有TypeScript的定义,或者你已经填充了一些JavaScript原语。在这种情况下,你必须为这些位提供类型定义,以使编译错误消失。只要创建一个.d.ts文件并将其包含在tsconfig.json的files数组中,这样TypeScript编译器就会一直考虑它。在其中声明那些TypeScript不知道的位,作为any类型。一旦你消除了所有的错误,你就可以根据你的需要逐步将类型化引入到这些部分。 为了让TypeScript进入构建管道,还需要对构建管道进行一些(重新)配置的工作。正如在编译一章中提到的,外面有很多好的资源,我鼓励你寻找使用你想使用的工具组合的种子项目。 最大的障碍是学习曲线。我鼓励你一开始就用一个小项目来玩。看看它是如何工作的,它是如何构建的,它使用哪些文件,它是如何配置的,它在你的IDE中是如何运作的,它是如何结构的,它使用哪些工具,等等。如果你知道自己在做什么,将大型 JavaScript 代码库转换为 TypeScript 是可行的。阅读这篇博客,以在72小时内将60万行转换为TypeScript为例)。)只要确保你在跳转之前对语言有一个很好的掌握。

采用

TypeScript是开源的(Apache 2许可,见GitHub),并得到微软的支持。C#的首席架构师Anders Hejlsberg正在带头执行这个项目。这是一个非常活跃的项目;TypeScript团队在过去几年中发布了很多新功能,而且还有很多很棒的功能计划要发布(见路线图)。 一些关于采用和流行的事实。

  • 2017年StackOverflow开发者调查中,TypeScript是最受欢迎的JavaScript转码器(总排名第9),并在最受喜爱的编程语言类别中获得第三名。
  • 2018年js状态调查中,TypeScript被宣布为JavaScript风味类别的两个大赢家之一(另一个是ES6)。
  • 2019年StackOverlow deverloper调查中,TypeScript上升到专业开发人员中最受欢迎的语言的第9位,超过了C和C++。在最受欢迎的语言中,它再次占据了第三位。
评论(10)

"TypeScript Fundamentals"--由Dan WahlinJohn Papa的Pluralsight视频课程是一个非常好的,目前(2016年3月25日)已经更新以反映TypeScript 1.8,介绍Typescript。

对我来说,真正好的功能是界面模块、实现AMD的简易性,以及在IE中调用Visual Studio Typescript调试器的可能性。

总结一下。如果按照预期使用,Typescript可以使JavaScript编程更可靠,更容易。在整个SDLC中,它可以显著提高JavaScript程序员的生产力。

评论(3)