首页 文章

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

提问于
浏览
1385

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

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

5 回答

  • 9

    我最初写的这个答案当Typescript仍然热销时 . 五年后,这是一个很好的概述,但请看下面的Lodewijk的答案更深入

    1000英尺查看...

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

    要了解我的意思,请观看语言Microsoft's introductory video .

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

    它是开源的,但如果您使用支持的IDE,则只能在键入时获得聪明的Intellisense . 最初,这只是微软的Visual Studio(也在Miguel de Icaza的博客文章中提到) . 这些天,other IDEs offer TypeScript support too .

    还有其他类似的技术吗?

    CoffeeScript,但这确实有不同的用途 . 恕我直言,CoffeeScript为人类提供了可读性,但TypeScript还通过其可选的静态类型为工具提供了深度可读性(请参阅此recent blog post以获得更多批评) . 还有Dart但是这是一个完全替代JavaScript(虽然它can produce JavaScript code

    示例

    举个例子,这里有一些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() 方法返回一个字符串 .

    调试打字稿

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

    想了解更多?

    我最初写的这个答案当Typescript仍然热卖时 . 有关更多当前详细信息,请查看此问题的Lodewijk's answer .

  • 815

    TypeScript Fundamentals ” - 由 Dan WahlinJohn Papa 组成的Pluralsight视频课程非常好,目前(2016年3月25日)已更新,以反映TypeScript 1.8对Typescript的介绍 .

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

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

  • 62

    所有浏览器支持和预编译的Ecma脚本5(ES5) . ES6 / ES2015和ES / 2016今年出现了很多变化,所以为了弹出这些变化,两者之间应该关注所以TypeScript .

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

    •TypeScript的一大优势是我们在投入 生产环境 之前就确定了与类型相关的问题 . 如果存在任何类型不匹配,则允许单元测试失败 .

  • 33

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

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

  • 1089

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

    与JavaScript的关系

    TypeScript是现代JavaScript类型 . 它是关于尽早捕获错误并使您成为更高效的开发人员,同时利用JavaScript社区 .

    JavaScript通过ECMAScript标准进行标准化 . 较旧的浏览器不支持较新的ECMAScript标准的所有功能(请参阅此table) . TypeScript支持新的ECMAScript标准,并将它们编译为您选择的(较旧的)ECMAScript目标(当前目标是3,5和6 [a.k.a. 2015]) . 这意味着您可以使用ES2015和的功能超出,像模块,lambda函数,类,扩展运算符和解构,同时保持向后兼容旧浏览器 .

    类型支持不是ECMAScript标准的一部分,可能永远不会归因于解释性质而不是JavaScript的编译性质 . TypeScript的类型系统非常丰富,包括:接口,枚举,混合类型,泛型,联合/交集类型,访问修饰符等等 . TypeScript的official website概述了这些功能 . 今天打字稿的类型系统与其他类型语言相当,在某些情况下可以说更强大 .

    与其他JavaScript定位语言的关系

    与其他编译为JavaScript的语言相比,TypeScript具有独特的理念 . JavaScript代码是有效的TypeScript代码; TypeScript是JavaScript的超集 . 您几乎可以将 .js 文件重命名为 .ts 文件并开始使用TypeScript(请参阅下面的"JavaScript interoperability") . TypeScript文件被编译为可读的JavaScript,因此可以回溯,并且理解编译的TypeScript并不困难 . TypeScript Build 在JavaScript成功的基础上,同时改善了它的弱点 .

    一方面,您有未来的证明工具,它们采用现代ECMAScript标准并将其编译为较旧的JavaScript版本,其中Babel是最受欢迎的版本 . 另一方面,您的语言可能与针对JavaScript的JavaScript完全不同,例如Coffeescript,Clojure,Dart,Elm,Haxe,ScalaJs以及更多主机(请参阅此list) . 这些语言虽然可能比JavaScript未来可能带来的更好,但却没有找到足够的采用它们的未来得到保证的风险 . 您可能也很难找到有经验的开发人员使用其中一些语言,尽管您会发现这些语言通常会更加热情 . 使用JavaScript的Interop也可以更多地涉及,因为它们实际上远离了JavaScript .

    TypeScript处于这两个极端之间,从而 balancer 风险 . TypeScript不是任何标准的危险选择 . 如果您熟悉JavaScript,则需要花费很少的精力,因为它不是一种完全不同的语言,具有出色的JavaScript互操作性支持,并且最近已经有很多采用 .

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

    JavaScript是动态类型的 . 这意味着JavaScript在运行时实际实例化之前不知道变量的类型 . 这也意味着可能为时已晚 . TypeScript为JavaScript添加了类型支持 . 如果你正确地玩牌,你可以完全根除某些类型的某些变量的错误假设所造成的错误(你输入代码的严格程度如何,或者你输入的代码完全取决于你) .

    通过使用类型推断,TypeScript使输入更容易,而且更少显式 . 例如:TypeScript中的 var x = "hello"var x : string = "hello" 相同 . 该类型只是从其使用中推断出来的 . 即使你没有明确地输入类型,它们仍然可以帮助你避免做一些否则会导致运行时错误的事情 .

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

    类型具有与之相关的成本 . 首先,有一个学习曲线,其次,当然,使用适当的严格类型设置代码库会花费你更多的时间 . 根据我的经验,这些成本对于您与他人共享的任何严格代码库都是完全值得的 . A Large Scale Study of Programming Languages and Code Quality in Github建议"that statically typed languages in general are less defect prone than the dynamic types, and that strong typing is better than weak typing in the same regard" .

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

    对于那些具有正系数的人,我们可以预期该语言与其他条件相同,更多的缺陷修复 . 这些语言包括C,C,JavaScript,Objective-C,Php和Python . Clojure,Haskell,Ruby,Scala和TypeScript等语言都具有负系数,这意味着这些语言不太可能导致缺陷修复提交 .

    增强的IDE支持

    TypeScript的开发经验是对JavaScript的一次重大改进 . Type富集类型的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 的变量仍然是可能的 . 但是,使用2.0版本的TypeScript,您可以通过使用非可空类型来消除这些类型的错误 . 其工作原理如下:

    启用严格空检查( --strictNullChecks 编译器标志)后,TypeScript编译器将不允许将 undefined 分配给变量,除非您明确声明它是可空类型 . 例如, let x : number = undefined 将导致编译错误 . 这完全符合类型理论,因为 undefined 不是数字 . 可以将 x 定义为 numberundefined 的和类型以更正此: 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.
    

    在2016年的 Session 期间,TypeScript Anders Hejlsberg的联合设计师对此功能进行了详细的解释和演示:video(从44:30到56:30) .

    编译

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

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

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

    有适用于WebpackGulpGrunt的TypeScript编译插件,以及几乎所有其他JavaScript构建工具 . TypeScript文档在integrating with build tools上有一节涵盖了它们 . 如果您想要更多的构建时间检查,也可以使用linter . 还有很多种子项目可以让你开始使用TypeScript,结合其他一些技术,如Angular 2,React,Ember,SystemJs,WebPack,Gulp等 .

    JavaScript互操作性

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

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

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

    有一点需要注意:类型定义必须与您在运行时使用的库的版本相匹配 . 如果不这样做,TypeScript可能会禁止您调用函数或取消引用存在的变量或允许您调用函数或取消引用不存在的变量,原因很简单,因为类型与编译时的运行时不匹配 . 因此,请确保为正在使用的库的正确版本加载正确版本的类型定义 .

    说实话,这有点麻烦,这可能是你不选择TypeScript的原因之一,而是选择像Babel这样的东西,而不必担心必须得到类型定义 . 另一方面,如果您知道自己在做什么,则可以轻松克服由于错误或缺少定义文件而导致的任何问题 .

    从JavaScript转换为TypeScript

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

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

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

    最大的障碍是学习曲线 . 我鼓励你先做一个小项目 . 了解它是如何工作的,如何构建,使用哪些文件,如何配置,如何在IDE中运行,如何构建,使用哪些工具等等 . 当你知道将大型JavaScript代码库转换为TypeScript时是可行的你在做什么 . 阅读此博客,例如converting a 600k lines to typescript in 72 hours) . 只需确保在跳跃之前掌握好语言 .

    收养

    TypeScript是开源的(Apache 2许可,请参阅github)并由Microsoft提供支持 . Anders Hejlsberg,C#的首席架构师是该项目的先锋 . 这是一个非常活跃的项目; TypeScript团队在过去几年中已经发布了许多新功能,并且仍计划推出许多很棒的功能(参见roadmap) .

    2017 StackOverflow developer survey TypeScript是最受欢迎的JavaScript转换器(总排名第9位),并且在最受欢迎的编程语言中获得第三名类别 .

相关问题