繁体   English   中英

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

[英]What is TypeScript and why would I use it in place of JavaScript? [closed]

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

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

我最初在 TypeScript 仍然很火的时候写了这个答案。 五年后,这是一个不错的概述,但请查看下面Lodewijk 的回答以获得更深入的信息

1000英尺视野...

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

要了解我的意思,请观看微软关于该语言的介绍视频

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

它是开源的,但如果您使用受支持的 IDE,您只能在键入时获得聪明的 Intellisense。 最初,这只是微软的 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()方法返回一个字符串。

调试打字稿

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

想知道更多?

我最初在 TypeScript 仍然很火的时候写了这个答案。 查看Lodewijk对此问题的回答,了解更多最新细节。

TypeScript 与 JavaScript 的关系

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

JavaScript 是由ECMA 的技术委员会 39开发的一种编程语言,该委员会由许多不同的利益相关者组成。 TC39 是一个由ECMA主办的委员会:一个内部标准组织。 许多不同的供应商(例如 Google、Microsoft、Oracle 等)对 JavaScript 有许多不同的实现。 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 添加了类型支持,并在编译为 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 启用此标志可为您提供更大程度的安全性,但也意味着您将不得不进行更多的输入。

类型具有与之相关的成本。 首先,有一个学习曲线,其次,当然,使用正确的严格类型设置代码库也会花费你更多的时间。 根据我的经验,在您与他人共享的任何严肃的代码库中,这些成本是完全值得的。 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 undefinedundefined is not a function cannot read property 'x' of undefined undefined is not a function这些错误通常是由 JavaScript 代码中的错误引起的。 开箱即用的 TypeScript 已经降低了发生此类错误的可能性,因为人们不能使用 TypeScript 编译器不知道的变量( any类型化变量的属性除外)。 但仍有可能错误地使用设置为undefined的变量。 但是,使用 2.0 版本的 TypeScript,您可以通过使用不可为 null 的类型来消除这些类型的错误。 其工作原理如下:

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

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

TypeScript 编译器还有一些其他技巧可以做,比如基于装饰器生成拦截代码,为不同的模块系统生成模块加载代码和解析JSX 但是,除了 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/”为前缀,来自 Github 存储库,名为absoluteTyped

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

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

从 JavaScript 转换为 TypeScript

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

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

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

最大的障碍是学习曲线。 我鼓励你首先尝试一个小项目。 看看它是如何工作的,它是如何构建的,它使用哪些文件,它是如何配置的,它如何在你的 IDE 中运行,它是如何构建的,它使用哪些工具等等。当你知道将一个大型 JavaScript 代码库转换为 TypeScript 是可行的你在做什么。 阅读此博客,例如在 72 小时内将 60 万行转换为打字稿)。 在进行跳转之前,请确保您对语言有很好的掌握。

采用

TypeScript 是开源的(Apache 2 许可,请参阅GitHub )并由 Microsoft 提供支持。 C# 的首席架构师Anders Hejlsberg是该项目的带头人。 这是一个非常活跃的项目; 在过去的几年里,TypeScript 团队已经发布了很多新功能,并且仍然计划推出很多很棒的功能(请参阅路线图)。

关于采用和受欢迎程度的一些事实:

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

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

TypeScript Fundamentals ”—— Dan WahlinJohn Papa的 Pluralsight 视频课程非常好,目前(2016 年 3 月 25 日)更新以反映 TypeScript 1.8,Typescript 介绍。

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

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

所有浏览器都支持和预编译的 Ecma 脚本 5 (ES5)。 ES6/ES2015 和 ES/2016 今年出现了很多变化,所以为了弹出这些变化,在它们之间有一些东西应该注意 TypeScript。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM