什么是TypeScript?为什么我要用它代替JavaScript?[关闭]


1694

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

JavaScript或可用的库无法执行的工作是什么,这使我有理由考虑?



以下是这方面的一些想法:blog.priceandcost.com/development/...
Jefim

Answers:


1298

我最初是在TypeScript仍然热销时写这个答案的。五年后,这是一个不错的概述,但请查看以下Lodewijk的答案以获取更多深度

1000英尺查看...

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

要了解我的意思,请观看有关该语言的Microsoft入门视频

对于大型JavaScript项目,采用TypeScript可能会导致软件更强大,同时仍可以在运行常规JavaScript应用程序的地方进行部署。

它是开源的,但是如果您使用受支持的IDE,则只有在键入时才能获得聪明的Intellisense。最初,这只是Microsoft的Visual Studio(也在Miguel de Icaza的博客文章中提到)。如今其他IDE也提供TypeScript支持

还有其他类似的技术吗?

CoffeeScript,但这确实有不同的用途。恕我直言,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通过Sourcemap提供直接调试支持。有关更多详细信息,请参见此堆栈溢出问题:使用Visual Studio调试TypeScript代码

想知道更多?

我最初是在TypeScript仍然热销时写这个答案的。查看Lodewijk对这个问题的答案,以获取更多当前的详细信息。


103
WebStorm现在在TypeScript上提供了不错的IntelliSense,并且是多平台的。
Radek

26
这些工具的问题在于,您永远无法获得javascript的全部性能。是的,它提供了良好的可读性,但是编译后的代码有时很笨拙。您依靠第三方工具来编写本机javascript,我认为这不是可行的方法,就像将一种语言转换为另一种语言一样。想要将一种非另一种语言的行为更改为您喜欢的另一种语言,这是愚蠢而愚蠢的。......(第1部分结束)......
2015年

56
@Erwinus:您是否仍在使用汇编器编程?
VikciaR

11
@Erwinus您正在假设TypeScript的工作方式。您可以将普通JavaScript编写为TypeScript,并让编译器仅进行编译时类型检查。这样做不会造成性能损失。
Thoughtrepo 2015年

41
@Erwinus TypeScript的重点是提供编译时类型检查。如果您没有看到其中的价值,那很好。TypeScript被称为“您的第一个单元测试”。有很多资源讨论了可选类型检查是否有价值,并且比我们在这里可以做的更多。我并不是想说服您任何事情,只是要纠正一个误解。
Thoughtrepo

1052

TypeScript与JavaScript的关系

打字稿是一个JavaScript的类型化超编译为普通的JavaScript - typescriptlang.org

JavaScript是由EMCA技术委员会39开发的一种编程语言,该委员会由许多不同的利益相关者组成。TC39是ECMA主办的委员会:内部标准组织。JavaScript由许多不同的供应商(例如Google,Microsoft,Oracle等)具有许多不同的实现。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添加了类型支持。如果您正确地玩牌(完全取决于您键入代码的严格性或完全取决于自己的代码),则可以完全消除由错误假设某个变量属于某种类型而导致的错误。

通过使用类型推断,TypeScript使键入变得更容易,并且显式性更低。例如:var x = "hello"在TypeScript中与相同var x : string = "hello"。类型仅是根据其用途推断出来的。即使您没有明确键入类型,它们仍然存在,可以避免您执行某些操作,否则将导致运行时错误。

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

类型具有与之相关的成本。首先,有一个学习曲线,其次,当然,使用适当的严格类型设置代码库也将花费您更多的时间。以我的经验,在与他人共享的任何严肃的代码库上,这些成本是完全值得的。在Github中对编程语言和代码质量进行的大规模研究表明:“通常,静态类型的语言比动态类型的缺陷倾向性小,并且从相同的角度来看,强类型强于弱类型”。

有趣的是,这篇论文发现TypeScript的错误发生率比JavaScript少:

对于那些具有正系数的人,我们可以期望该语言与更多的缺陷修复程序相关联。这些语言包括C,C ++,JavaScript,Objective-C,Php和Python。Clojure,Haskell,Ruby,Scala和TypeScript等语言均具有负系数,这意味着这些语言导致缺陷修复提交的可能性低于平均值。

增强的IDE支持

TypeScript的开发经验是对JavaScript的极大改进。TypeScript编译器会根据其丰富的类型信息实时通知IDE。这提供了两个主要优点。例如,使用TypeScript,您可以安全地进行重构,例如在整个代码库中进行重命名。通过代码完成,您可以获得有关库可能提供的任何功能的内联帮助。不再需要记住它们或在在线参考中查找它们。在您忙于编码时,编译错误将直接在IDE中以红色蠕变线报告。总而言之,与使用JavaScript相比,这可以显着提高生产率。一个人可以花费更多的时间进行编码,而花费较少的调试时间。

有各种各样的IDE对TypeScript具有出色的支持,例如Visual Studio Code,WebStorm,Atom和Sublime。

严格的空检查

形式上的运行时错误,cannot read property 'x' of undefined或者undefined is not a function通常是由JavaScript代码中的错误引起的。由于无法使用TypeScript编译器不知道的变量(any类型化变量的属性除外),因此TypeScript可以立即降低发生此类错误的可能性。仍然有可能错误地使用设置为的变量undefined。但是,使用TypeScript 2.0版,您可以通过使用非空类型来一起消除这些类型的错误。其工作原理如下:

启用严格的空检查(--strictNullChecks编译器标志)后,undefined除非您明确声明其为可空类型,否则TypeScript编译器将不允许分配给变量。例如,let x : number = undefined将导致编译错误。因为undefined不是数字,所以这与类型理论非常吻合。可以定义x为的总和类型numberundefined对此进行更正:let x : number | undefined = undefined

一旦已知类型为可为空,这意味着该类型也可以为nullundefined,则TypeScript编译器可以通过基于控制流的类型分析来确定您的代码是否可以安全地使用变量。换句话说,当您undefined通过例如一条if语句检查变量时,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 Anders Hejlsberg的2016年会议联合设计师对此功能进行了详细说明和演示:视频(从44:30到56:30)。

汇编

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

TypeScript编译器可以在生成的.js文件中内联源地图信息,或创建单独的.map文件。调试实用程序(例如Chrome DevTools和其他IDE)可以使用源地图信息,以将JavaScript中的行与在TypeScript中生成它们的行相关联。这使您可以在运行时直接在TypeScript代码上设置断点和检查变量。源地图信息的效果很好,距TypeScript尚有很长时间,但调试TypeScript通常不如直接使用JavaScript那样好。以 this关键字为例。由于this自2015年以来,闭包周围的关键字语义发生了变化,因此this在运行时可能实际上存在一个称为的变量_this(请参阅此答案)。)。这可能会在调试过程中使您感到困惑,但是如果您了解或检查JavaScript代码,通常不会出现问题。应当指出,巴别塔也遭受同样的问题。

TypeScript编译器还可以完成其他一些技巧,例如基于装饰器生成拦截代码,为不同模块系统生成模块加载代码以及解析JSX。但是,除了Typescript编译器之外,您可能还需要构建工具。例如,如果要压缩代码,则必须在构建过程中添加其他工具。

有TypeScript编译插件可用于WebpackGulpGrunt以及几乎所有其他JavaScript构建工具。TypeScript文档中有一节介绍如何涵盖所有内容的构建工具集成。一个棉短绒也可如果你想更多的编译时间检查。还有大量的种子项目,可以带您开始使用TypeScript并结合其他许多技术,例如Angular 2,React,Ember,SystemJS,Webpack,Gulp等。

JavaScript互操作性

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

定义可以采用的最简单形式是允许以任何方式使用标识符。例如,使用Lodash时,单个行定义文件declare var _ : any将允许您调用所需的任何函数_,但是,当然,您仍然会犯错误:_.foobar()将是合法的TypeScript调用,但当然是,在运行时是非法呼叫。如果您需要适当的类型支持和代码完成功能,则您的定义文件必须更加精确(有关示例,请参见lodash定义)。

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

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

坦白地说,这样做有一点麻烦,这可能是您不选择TypeScript的原因之一,而是选择了Babel之类的东西,而该东西完全不需要获得类型定义。另一方面,如果您知道自己在做什么,则可以轻松解决由于定义文件不正确或丢失而引起的任何类型的问题。

从JavaScript转换为TypeScript

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

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

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

最大的障碍是学习曲线。我鼓励您起初先做一个小项目。查看它的工作方式,生成方式,使用的文件,配置的方式,在IDE中的功能,结构的使用,使用的工具等。将大型JavaScript代码库转换为TypeScript是可行的,只要您知道你在做什么。阅读此博客,例如有关在72小时内将60万行转换为打字稿的信息。进行跳跃之前,请确保您已掌握该语言。

采用

TypeScript是开源的(Apache 2许可,请参见GitHub),并得到Microsoft的支持。C#的首席架构师Anders Hejlsberg负责该项目。这是一个非常活跃的项目。在过去的几年中,TypeScript团队已经发布了许多新功能,并且仍然计划推出许多出色的功能(请参阅路线图)。

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


25
“ JavaScript代码是有效的TypeScript代码”-实际上并非总是如此。我的意思是像if(1 ==='1'){}这样的代码给您TS中的错误,而JS中没有。但是大多数时候,如果JS代码写得好,那是真的。
Maciej Bukowski

3
如果您失去了宝贵的生产时间,而在缺少的半角冒号上烦恼,那么用Typescript书写将可以节省生命。
SoSufi'3

3
不建议使用Typings,而目前的最佳做法是just npm(或yarninstall @types/foo。你能更新你的答案吗?
杰德·福克斯

13
TL; DR将在这个答案中
变得更加省力

8
@MaciejBukowski即使在这种情况下TypeScript确实会抱怨,您仍然会获得有效的JS输出(它将是使用TypeScript编译/转译的JS代码)。因此,它是“有错误的编译”,并且不是无效的TypeScript。在TypeScript规范中记录下来,任何有效的JS代码都必须是有效的TS代码。
Pac0

83

TypeScript的作用类似于CSS的less或sass。它们是它的超级集,这意味着您编写的每个JS代码都是有效的TypeScript代码。另外,您可以使用它添加到语言中的其他优点,并且转译后的代码将是有效的js。您甚至可以设置要在其上生成结果代码的JS版本。

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


4
最好的TL; DR是TS的页面:“ TypeScript是JavaScript的类型化超集,可编译为纯JavaScript。”
Juan Mendes

1
它没有回答“我为什么要使用它”。这里的tl; dr将是:1)向JavaScript添加可选的静态类型。类型可以帮助在编译时捕获错误,并更好地记录程序。2)您可以编写新的 JavaScript(ES6 / ES7 / ESnext)并将其编译回ES5,这对于支持较旧的浏览器是必需的;我已经在tsmean.com/articles/vs/typescript-vs-javascript中详细说明了一些有关tl; dr的信息
狂暴的

1
“转译的代码将是有效的JS”-如果您问我,这就是TypeScript的致命弱点。这意味着他们不能向JS添加一些非常有用的功能。最值得注意的是运行时类型检查。具有编译器时类型的安全性只是为了丢失从I / O读取的任何运行时数据,或者任何时候从其他JS不安全地调用已转译的代码而丢失它时,都会有点烦人。
杰斯

44

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

对我来说,除了智能感知的可能性之外,真正好的功能还包括接口模块,实现AMD的简便性以及在通过IE调用时使用Visual Studio Typescript调试器的可能性。

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


9
什么是SDLC?AMD?
Oooogi

15
@ Oooogi,SDLC ==软件开发生命周期。AMD ==异步模块定义。后者特定于JavaScript,而前者在范围上相当通用。
Dimitre Novatchev

2
“易于实施AMD,...”-我读了那本书,并认为这是某种线程撕裂程序优化之类的东西。
jrh '18

15

所有浏览器均支持并预先编译的Ecma脚本5(ES5)。ES6 / ES2015和ES / 2016今年进行了许多更改,因此要弹出这些更改,请务必谨慎之间使用TypeScript。

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

•TypeScript的一大优势是我们可以在投入生产之前及早识别与类型相关的问题。如果类型不匹配,这会使单元测试失败。


2
这不是每年的伙伴!..他们在漫长的等待之后改变了规格
Subham Tripathi

...,您可以将这些变化与Microsoft紧密联系在一起。;-)
Trober

2
@SubhamTripathi它很逐年递增。ES2015,ES2016,ES2017,以及从现在起到该语言终止使用为止。它不是每一年,在2015年之前,但它现在是。继续搜索“ TC39流程”以了解更多信息。
daemonexmachina

1
javascript社区中对类型检查的需求很大吗?我只是没有很多与类型检查有关的错误。
Box and Cox
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.