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


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

JavaScript或可用库无法做什么,这会让我有理由考虑它?


1277
2017-10-02 16:37


起源


看看这个博客: blogs.msdn.com/b/somasegar/archive/2012/10/01/... - Andreas
@Lorenzo - 因为提出正确的问题是成功的一半,这是正确的问题。这是人们的问题 应该 在遇到另一种技术复杂问题时要问问自己。 TypeScript是那些罕见的东西之一。 - Peter Wone
这里有一些说明: basarat.gitbooks.io/typescript/content/docs/why-typescript.html - basarat
问题在2012年被问到,“好”问题的定义是不同的,我认为这是件好事 - chiliNUT
我喜欢没有人真正回答你的问题。他们只回答了第一部分。 为什么有人想要使用或不使用TypeScript?这就像人们之前从未触及它或者害怕表达任何判断。 - Andrew


答案:


我最初在打字稿时仍然写了这个答案   热现成的印刷机。五年后,这是一个好的概述,但看   在 Lodewijk的回答 下面有更深入的内容

1000英尺的视图......

打字稿 是JavaScript的超集,主要提供可选的静态类型,类和接口。其中一个重要好处是使IDE能够提供更丰富的环境来发现常见错误 在键入代码时

要了解我的意思,请注意 微软的介绍性视频 关于语言。

对于大型JavaScript项目,采用TypeScript可能会产生更强大的软件,同时仍可部署常规JavaScript应用程序。

它是开源的,但如果您使用支持的IDE,则只能在键入时获得聪明的Intellisense。最初,这只是微软的Visual Studio(也在博客文章中提到过 米格尔·德伊卡萨)。这些天, 其他IDE也提供TypeScript支持

还有其他类似的技术吗?

CoffeeScript的,但这确实有不同的用途。恕我直言,CoffeeScript为人类提供了可读性,但TypeScript也提供了深度可读性 工具 通过其可选的静态类型(见此 最近的博文 为了更多的批评)。还有  但这完全取代了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() method返回一个字符串。

调试Typescript

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

想知道更多?

我最初写的这个答案当Typescript仍然热卖时。查看 Lodewijk的回答 针对这个问题提供更多当前细节。


1024
2017-10-02 16:41



WebStorm现在可以在TypeScript上提供出色的IntelliSense,并且是多平台的。 - Radek
这些工具的问题在于你永远无法从javascript中获得完整的性能。是的,它提供了良好的可读性,但编译的代码有时非常笨重。您依靠第三方工具编写本机javascript,我认为这不是一种方法,就像将语言转换为另一种语言一样。想要改变一种不是另一种语言的语言,就像你喜欢的另一种语言一样,这是愚蠢而愚蠢的。 ......(第1部分结束)...... - Codebeat
@Erwinus:你还用汇编程序编程吗? - VikciaR
不,@ Erwinus,该代码是可选的。您可以在TypeScript中轻松编写纯JavaScript版本。 - thoughtrepo
@Erwinus TypeScript的要点是提供编译时类型检查。如果你没有看到它的价值,那就完全没问题了。 TypeScript被称为“您的第一个单元测试”。有许多资源可以讨论可选类型检查是否具有价值,并且比我们在此处可以做的更详细。我不是想要说服你什么,只是纠正一个误解。 - thoughtrepo


虽然接受的答案很好,但我觉得这时候TypeScript正义并没有。现在已经不是早期了。现在,TypeScript正在寻找更多的应用,其中几个流行的框架是用TypeScript编写的。您现在应该选择TypeScript而不是JavaScript的原因很多。

与JavaScript的关系

JavaScript通过ECMAScript标准进行标准化。并非所有使用的浏览器都支持新的ECMAScript标准的所有功能(请参阅此内容) )。 TypeScript支持新的ECMAScript标准,并将它们编译为您选择的(较旧的)ECMAScript目标(当前目标是3,5和6 [a.k.a. 2015])。这意味着您可以使用ES2015及更高版本的功能,如模块,lambda函数,类,扩展运算符,解构,今天。它当然也增加了类型支持,它不是任何ECMAScript标准的一部分,并且可能永远不会归因于解释性质而不是JavaScript的编译性质。 TypeScript的类型系统相对丰富,包括:接口,枚举,混合类型,泛型,并集和交集类型,访问修饰符等等。该 官方网站 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,ScalaJs以及更多主机(请参阅此内容) 名单)。这些语言虽然可能比JavaScript未来可能带来的更好,但却没有找到足够的采用它们的未来得到保证的风险。您可能也很难找到有经验的开发人员使用其中一些语言,尽管您会发现这些语言通常会更加热情。使用JavaScript的Interop也可以更多地涉及,因为它们实际上远离了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中的一个有效函数,可以使用它调用 任何 一种参数,即使用字符串调用它显然会导致a 运行 错误。就像你习惯于JavaScript一样。这是有效的,因为当没有显式分配类型并且无法推断类型时,例如在divideByTwo示例中,TypeScript将隐式指定类型 any。这意味着divideByTwo函数的类型签名自动变为 function divideByTwo(x : any) : any。有一个编译器标志禁止此行为: --noImplicitAny。启用此标志可以提高您的安全性,但也意味着您需要进行更多的打字。

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

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

对于那些具有正系数的人,我们可以期待这种语言   在其他条件不变的情况下,有更多的缺陷修复。   这些语言包括C,C ++, JavaScript的,Objective-C,Php和   蟒蛇。语言Clojure,Haskell,Ruby,Scala和 打字稿,   都有负系数,暗示这些语言较少   可能比平均值导致缺陷修复提交。

增强的IDE支持

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

有各种各样的IDE对TypeScript有很好的支持,比如Visual Studio和VS代码,Atom,Sublime和IntelliJ / WebStorm。

严格的空检查

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

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

一旦知道一个类型可以为空,这意味着它的类型也可以是有价值的 null 要么 undefined,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.

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

汇编

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

TypeScript编译器可以在生成的.js文件中内联源地图信息,或者创建单独的.map文件。调试实用程序(如Chrome DevTools和其他IDE)可以使用源映射信息将JavaScript中的行与在TypeScript中生成它们的行相关联。这使您可以直接在TypeScript代码上设置断点并在运行时检查变量。源地图信息非常好用,它早在TypeScript之前就已存在,但调试TypeScript通常不如直接使用JavaScript时那么好。拿走 this 关键字例如。由于改变了语义 this 自ES2015以来关闭的关键字, this 在运行时可能实际上存在一个名为的变量 _this(看到 这个答案)。这可能会在调试期间使您感到困惑,但如果您了解它或检查JavaScript代码,通常不会出现问题。应该指出,巴贝尔遇到了完全相同的问题。

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

有可用的TypeScript编译插件 的WebPack咕噜 几乎任何其他JavaScript构建工具。 TypeScript文档有一节 与构建工具集成 涵盖所有。一个 棉短绒 如果您想要更多的构建时间检查,也可以使用它。还有很多种子项目可以让你开始使用TypeScript,结合其他一些技术,如Angular 2,React,Ember,SystemJs,WebPack,Gulp等。

JavaScript互操作性

由于TypeScript与JavaScript密切相关,因此具有出色的互操作性功能,但在TypeScript中使用JavaScript库需要一些额外的工作。 TypeScript定义 需要使TypeScript编译器理解函数调用 _.groupBy 要么 angular.copy 要么 $.fadeOut 事实上并非违法的陈述。这些功能的定义放在 .d.ts 文件。

定义可以采用的最简单的形式是允许以任何方式使用标识符。例如,使用时 Lodash,单行定义文件 declare var _ : any 将允许您调用您想要的任何功能 _,但当然你仍然可以犯错误: _.foobar() 将是一个合法的TypeScript调用,但在运行时当然是非法调用。如果您需要正确的类型支持和代码完成,您的定义文件需要更精确(请参阅 lodash定义 例如)。

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

有一点需要注意:类型定义必须与您在运行时使用的库的版本相匹配。如果不这样做,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不知道的那些位作为类型 any。一旦消除了所有错误,您可以根据需要逐步为这些部分引入打字。

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

最大的障碍是学习曲线。我鼓励你先做一个小项目。了解它是如何工作的,如何构建,使用哪些文件,如何配置,如何在IDE中运行,如何构建,使用哪些工具等等。当你使用大型JavaScript代码库转换为TypeScript时非常可行知道你在做什么,但如果不这样做,可能会令人沮丧。

采用

TypeScript是开源的(Apache 2许可,请参阅 github上)并得到微软的支持。 安德斯海尔斯伯格,C#的首席架构师正率先推动该项目。这是一个非常活跃的项目; TypeScript团队在过去几年中已经发布了许多新功能,并且仍计划推出许多很棒的功能(参见 路线图)。

在里面 2017年StackOverflow开发人员调查 TypeScript是最受欢迎的JavaScript转换器(总排名第9位),并且在最受欢迎的编程语言类别中获得第三名。


729
2018-01-27 21:23



“JavaScript代码是有效的TypeScript代码” - 实际上并非总是如此。我的意思是代码if if(1 ==='1'){}在TS中给你一个错误而在JS中没有。但大多数时候,如果JS代码编写得很好,那就是真的。 - Maciej Bukowski
如果你已经失去了宝贵的生产时间,而不是因为缺少半结肠而烦恼,那么用打字稿写下就可以节省生命。 - SoSufi
打字已被弃用,目前的最佳做法是公正的 npm (要么 yarn) install @types/foo。你能更新你的答案吗? - J F
TL; DR 在这个答案中会更安心;) - Qback
@NickHodges没关系,还有6个人可以;) - Wayne Werner


TypeScript的功能类似于CSS或更少的功能。它们是它的超级集合,这意味着您编写的每个JS代码都是有效的TypeScript代码。另外,您可以使用它添加到语言中的其他好东西,并且转换后的代码将是有效的js。您甚至可以设置希望生成代码的JS版本。

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


54
2018-02-11 20:32



不知何故,这有助于我比任何一个高度赞成的答案更好地理解。我想我只需要一个TL; DR,ELI5答案。 - TVann
最佳TL; DR是TS的页面:“TypeScript是JavaScript的类型超集,可编译为纯JavaScript。” - Juan Mendes
它没有回答“我为什么要使用它”。这里的tl; dr将是:1)向JavaScript添加可选的静态类型。类型可以帮助在编译时捕获错误并更好地记录您的程序。 2)你可以写 新 JavaScript(ES6 / ES7 / ESnext)并将其编译回ES5,这是支持旧浏览器所必需的;我已经详细说明了一下 tsmean.com/articles/vs/typescript-vs-javascript 对于那些对tl感兴趣的人;博士 - bersling
“转换后的代码将是有效的JS” - 如果你问我,这就是TypeScript的致命弱点。这意味着他们无法为JS添加几个非常有用的功能;最为显着地 运行 类型检查。让编译器时间类型安全只是为了从I / O读入的任何运行时数据丢失它,或者任何时候从其他JS不安全地调用转换后的代码,这有点烦人。 - Jez


TypeScript基础知识“ - 一个Pluralsight视频课程 丹华林 和 约翰帕帕 是一个非常好的,目前(2016年3月25日)更新,以反映TypeScript 1.8,Typescript的介绍。

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

总结一下:如果按预期使用,Typescript可以使JavaScript编程更可靠,更容易。与完整的SDLC相比,它可以显着提高JavaScript程序员的工作效率。


30
2017-12-27 04:18



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


所有浏览器支持和预编译的Ecma脚本5(ES5)。 ES6 / ES2015和ES / 2016今年出现了很多变化,所以为了弹出这些变化,两者之间应该关注所以TypeScript。 •TypeScript是Types - >意味着我们必须定义每个属性和方法的数据类型。如果您了解C#,那么Typescript很容易理解。 •TypeScript的一大优势是我们在投入生产之前就确定了与类型相关的问题。如果存在任何类型不匹配,则允许单元测试失败。


7
2018-06-06 12:14



这不是每年的好友!他们在经过漫长的等待后改变了规格 - Subham Tripathi
......而且,这些变化可以与微软联系起来。 ;-) - Trober
@SubhamTripathi非常 是 每年。 ES2015,ES2016,ES2017,从现在开始直到语言死亡。它 不 每年,在2015年之前,但它现在。搜索“TC39流程”以了解更多信息。 - daemonaka
倾向于C#评论。适用于TypeScript的所有C#知识仅适用于JavaScript(考虑更高阶函数)并且与TypeScript无关。 - Aluan Haddad