为什么要用 TypeScript

为什么是TypeScript?

使用 TypeScript,减少运行时错误,降低测试和维护成本。

JavaScript

先来看一张 meme 图:


0=='0'

知道为什么会这样吗?很好!继续往下看吧。如果你还不知道这是为什么,可以立刻必应谷歌百度寻找答案,或者继续往下看。

JavaScript起源

JavaScript是一种解释型或即时编译型的动态类型语言,最早被用于浏览器,作为基于浏览器的脚本语言出现。现代的JavaScript已经不再局限于浏览器,通过Node.js和其他运行时环境运行在桌面和服务器端。因为其动态和轻量化的特点,JavaScript成为了最易学习的编程语言之一。

type

令人头大的模板泛型?在JavaScript里,你不需要!

JavaScript的问题

JavaScript的动态类型特性减少了代码量,提高了开发效率和基于Web浏览器的应用场景中客户端与服务端数据传输的效率。然而,现在的JavaScript已经不再只是运用在Web浏览器场景中。动态类型特点带来了一系列问题:

  • 臭名昭著的'undefined' is not a function.
  • 喜闻乐见的TypeError: Cannot read property 'foobar' of undefined
  • 实际返回值和预期返回值不同
  • 大量的assert类型断言
  • ...
type

将一个字符串类型与整型相加,但是JavaScript返回了一个字符串类型。

一个典型场景:

let foo = (bar, baz) => {
    let qux;
    // 这里省略一些过程,反正api调用者也无需关心,bula bula
    return qux;
}

假设这是一个接口,程序猿A将这个接口交给了程序猿B。如果A和B都是江湖老油条,交流通畅,文档完备,那么这段代码在他们手中就不会出现问题。

可是,如果A和B的沟通存在问题,B并没有完全理解如何使用该接口,那么问题来了:
bar 和 baz 是什么类型?qux 又是什么?foo 将返回一个数字、字符串、对象还是函数?由于暴露给B的内容只有函数名、形式参数列表和返回值,而在 JavaScript中 也没有为这些内容指定类型,B将不知道如何保证输入和输出的有效性。更要命的是,如果该函数还要隐式地接受剩余参数并进行处理,B将更无从下手。(现在我们有了万能的IDE们,可以辅助我们使用各种函数和接口。)

由于缺乏类型限定,无效的输出会导致各种各样的意外结果,如果A确实在函数内部使用断言,在类型不满足需求时解释器将会打断代码执行,阻止错误进一步破坏整个应用的逻辑。但是,对于解释型的JavaScript来说,所有断言和错误都将发生在运行时,这将使得部分网页脚本无法继续运行下去。

js

如果你还不知道这个梗,恭喜你!你又掌握了一个关于JavaScript的特性。在控制台中输入typeof name寻找答案。

总而言之,JavaScript 的解释型和动态类型特性会导致意料之外的结果,甚至导致严重逻辑错误和程序崩溃。

不健全的 JavaScript 代码反而会降低程序员的开发效率,这就违反了 JavaScript 的设计初衷了。随着 JavaScript 向浏览器以外的场景扩展,让代码短小精悍以提高网络传输效率已不再是必须的要求,新的 EcmaScript 标准提供了一些更有效的类型判断方式,但这还远远不够,JavaScript难以胜任大型项目的开发。

JavaScript 急需一些编译型、静态类型语言的特性来弥补在这些运行环境中的不足,提高代码可读性,并减少运行时错误。

bad code

ES6增加的全等判断运算符,用以判断两个对象的值和类型是否都相等。

减少运行时错误

对于学习过 Dart 这门语言的程序猿,一定都知道 Dart 的设计团队花了多少精力在实现该语言的空安全特性上,空安全为编译前的编程过程提供了各项便利,使错误可以在运行前就被编辑器和编译器发现,大大降低了运行时错误发生的可能性,提高了整个程序运行过程中的安全性。而空安全实现中重要的一环,也是对类型:可空类型非空类型进行编译时检查,避免在运行时因为一个可空类型接收了 null 而出现类似null.length()的调用。

如果你还不知道 Dart ,目前流行的多平台前端框架 Flutter 就是基于该语言运作的。

Dart

引用 Bob Nystrom, Google Dart 团队工程师的话:

"开发者偏爱像 Dart 这样的静态类型语言,因为它通常可以让使用 IDE 的开发者通过类型检查发现错误。Bug 越早被发现,就能越早处理。当语言设计者在谈论“修复空引用错误”时,他们指的是加强静态类型检查器,使得诸如在可能为 null 的值上调用 .length 这样的错误能被检测到。"
原文链接

TypeScript

TypeScript

一张图说明 TypeScript 如何运作。

  1. 帅气无敌的程序猿你写下了帅气无敌的 TypeScript 代码
  2. TypeScript 将你帅气无敌的 TypeScript 代码编译为 JavaScript 代码
  3. 将 JavaScript 代码送入各种运行时环境进行解释运行

TypeScript起源

2012年,Microsoft 首次发布公开版本的 TypeScript 。TypeScript 在 JavaScript 的基础上增加静态类型定义和编译时检查,通过编译,可以将 TypeScript 转译为 JavaScript。

由于 TypeScript 是 JavaScript 的超集,任何原生的 JavaScript 代码都可以直接通过编译器检查并运行。TypeScript 的静态类型和编译大大降低了发生运行时错误的可能性,同时作为超集,TypeScript 依旧保留了 JavaScript 的灵活性,可谓是一举两得。

ts

TypeScript 实际上是 JavaScript 的超集,编译后的 TypeScript 就是去掉类型检查和其他限定的 JavaScript,而在使用 TypeScript 编辑代码时,编译器和 IDE 的编辑器会检查这些限定。

除了静态类型的定义和检查外,TypeScript 还引入了类、接口、模块、装饰器、命名空间等特性(ES6中也实现了部分),这些都是 JavaScript 想要胜任大型软件工程项目所急需的特性。

TypeScript的问题

如果要说 TypeScript 有什么问题,大概就是程序猿的学习成本和编译时的时间成本消耗、编译结果的空间成本消耗了。

对于那些从 JavaScript 入门的程序猿来说,静态类型检查、模板泛型、类、接口、继承是以往在 JavaScript 编程中不怎么接触,甚至是从来没有听说过的事物,想要从轻量化的 JavaScript 中走向 TypeScript 一类的静态类型语言需要一定时间来学习和积累经验。

此外,由于 TypeScript并不能直接用于 JavaScript 解释引擎,需要编译器将其编译为 JavaScript 代码后才可进行解释,并且添加静态类型检查的 JavaScript 代码会比无类型检查的代码更多更长,对于浏览器来说,在资源传输效率上这并不一定是一件好事。而在工程开发构建的过程中,程序猿也需要花费更多的时间来处理编译时错误和产出最终的 JavaScript代码。

但是,正如前文所说,劣质的 JavaScript 代码的开发和维护同样费时,并可能引发严重错误,消耗更多的时间成本,最终变成代码“屎山”。使用 TypeScript 来避免原生 JavaScript 中会被潜在引发的问题,从总体成本上来说仍然是值得的。当然,前提是程序猿编写的 TypeScript 代码也得是健壮有效的。更何况,现代的 JavaScript 已经不再只是在浏览器环境中运行,代码占用空间的影响并不像浏览器中那样大(现代浏览器同样可以通过缓存减少资源传输量)。

ts

TypeScript 确实提供了静态类型定义,但也有一个 any 类型表示可以接收任何类型。如果程序猿滥用 any,那 TypeScript 看起来和 JavaScript 也无异了……

TypeScript与现实

目前的主流前端框架 Vue、React、Angular 都支持使用 TypeScript 语法进行项目构建,浏览器外的运行时环境 Node.js 同样支持 TypeScript。通过使用 TypeScript 编译器,可以将 TypeScript 代码和一些原生 JavaScript 库内容混用,像使用原生 JavaScript 代码引用这些库内容一样在 TypeScript 中使用他们。TypeScript 依旧是目前构建大型 JavaScript 软件工程项目的选择之一。

Ts and Js

TypeScript 同样支持 ES6 标准。

结语

js

动态类型的 JavaScript 坏坏,但是何时何地都是这样吗?

TypeScript 并不是万金油,一门语言是否有效不仅取决于语言自身的设计,也受程序猿编写代码的影响。是 JavaScript 还是 TypeScript ?一切都由程序猿自己决定。切忌盲目随大流,一切从实际出发,实事求是,选择最适合工程项目的编程语言和框架吧!

你可能感兴趣的:(为什么要用 TypeScript)