TypeScript 被吹过头了?

更新日期: 2020-02-23阅读: 1.8k标签: TypeScript

开始看本文之前,我希望读者朋友们知道我在很大程度上是一位 TypeScript 粉丝。在我的前端 react 项目和各种后端 Node 工作里,所使用的主要编程语言都是 TypeScript。我是这条船上的人,但也确实有一些疑惑,想在这篇文章中讨论一下。到目前为止,我已经使用 TypeScript 写了至少三年的代码,涉及的项目不计其数,因此可以说 TypeScript 的确是走在了正路上,或者说满足了某种需求。

TypeScript 克服了一些难以逾越的障碍,成为了前端编程领域的主流之选。TypeScript 在 这篇文章 列出的最受欢迎编程语言中排名第七。

无论你是否在使用 TypeScript,不管多大规模的软件团队都应遵循以下实践:

  • 精心编写的单元测试应在合理范围内覆盖尽可能多的生产代码;
  • 结对编程——另一双眼睛可以捕捉到的远不止语法错误;
  • 良好的同行评审流程——正确的同行评审可以找出许多机器无法捕获的错误;
  • 使用 eslint 之类的 linter。

TypeScript 可以在这些基础之上增加额外的一层安全性,但我认为这在编程语言的需求列表中是排在非常靠后的位置上的。


TypeScript 并非健全的类型系统

我认为这可能是 TypeScript 当前版本面临的主要问题,但首先,我来定义一下什么是健全(sound)和不健全(unsound)的类型系统。

健全

一个健全的类型系统能确保你的程序不会进入无效状态。例如,如果一个表达式的静态类型是 string,则在运行时,对它求值时你肯定只会得到一个 string。

在健全的类型系统中,永远不会在编译时 或运行时 出现表达式与预期类型不匹配的情况。

当然, 健全性(soundness) 也是有级别的,具体含义可以斟酌。TypeScript 具有一定程度的健全性,并会捕获以下类型的错误:

// 类型'string'不能赋值给 类型'number'
constincrement = (i:number):number=> {returni +"1"; }

// 类型'"98765432"'的参数不能赋值给类型'number'的参数.
constcountdown:number= increment("98765432");

不健全

关于 Typescript,以下事实是非常明确的:100%的健全性不是它的目标,并且 TypeScript 的 非目标列表 中的 3 号非目标明确指出:

应用一个健全或“正确无误”的类型系统(不是我们的目标)。相反,要在正确性和生产力之间取得平衡。

这意味着不能保证变量在运行时具有定义的类型。我可以用下面一些人为的例子说明这一点:

interfaceA {
x:number;
}

leta: A = {x:3}
letb: {x:number|string} = a;
b.x ="unsound";
letx:number= a.x;// 不健全

a.x.toFixed(0);// 这啥?

上面的代码是不正确的,因为从 A 接口中可知 a.x 应该是一个数字。不幸的是,经过一些重新赋值后,它最终以一个字符串的形式出现,并且后面的代码能通过编译,但会在运行时出错。很不幸,这里显示的表达式可以正确编译:

a.x.toFixed(0);

我认为这可能是 TypeScript 的最大问题,那就是健全性不是它的目标。我仍会遇到许多运行时错误,这些错误没有被 tsc 编译器标记出来,但如果 TypeScript 有一个健全的系统就能做到了。采用这种方法,意味着 TypeScript 在健全和不健全的阵营之间是在脚踩两只船。这种摇摆路线遇上 any 类型就更严重了,我将在后文提到这一点。我还是得编写尽可能多的测试,这让我感到沮丧不已。当我第一次开始使用 TypeScript 时,我错误地得出了一个结论,以为以后就用不着编写这么多单元测试了。

TypeScript 挑战了现状,声称降低用户使用类型的认知开销比类型健全更重要。

我理解为什么 TypesScript 会走这条路,并且有一个观点指出,如果类型系统的健全性得到 100%保证,那么 TypeScript 的采用率就不会那么高了。随着 dart 语言逐渐流行(因为 Flutter 现已广泛应用),这个看法也被证伪了。健全性是 dart 语言的一个目标,可以参考 这里的讨论 。

TypeScript 的不健全性,以及它在严格的类型系统上开的一大堆天窗拖累了它的效率,让它在今天处于相当 鸡肋 的位置上,非常可惜。我的愿望是,随着 TypeScript 的流行,会有更多的编译器选项可供使用,从而使高级用户可以争取 100%的健全性。


TypeScript 不保证任何运行时类型检查

运行时类型检查不是 TypeScript 的目标之一,因此这种愿望可能永远不会实现。例如,在处理从 api 调用返回的 JSON 负载时,运行时类型检查会很有用。如果我们可以在类型级别上控制它,就用不着一整筐错误和许多单元测试了。

我们无法在运行时保证任何事情,因此可能会出现以下情况:

constgetFullName =async():string=>{
constperson: AxiosResponse =awaitapi();

//response.name.fullName 可能在运行时成为 undefined
returnresponse.name.fullName
}

有一些支持这种需求的库,例如 io-ts;虽然它很棒,但可能意味着你必须复制你的模型。


可怕的 any 类型和严格选项

any 类型就是字面意思,编译器允许任何操作或赋值。

TypeScript 往往在小事上表现很不错,但是人们习惯给花费时间超过 1 分钟的任何事物都来个 any 类型。我最近在一个 angular 项目中工作,看到很多这样的代码:

exportclassPerson {
public_id:any;
publicname:any;
publicicon:any;

TypeScript 会让你忘掉类型系统。你可以用一个 any 把所有事物的类型干掉:

("oh my goodness"asany).ToFixed(1);// 记得我提到健全性时说的话吗?

strict 编译器选项会启用以下编译器设置,这些设置会让事物看起来更健全:

  • –strictNullChecks
  • –noImplicitAny
  • –noImplicitThis
  • –alwaysStrict

还有 eslint 规则 @typescript-eslint/no-explicit-any。

any 的扩散会毁掉你类型系统的健全性。


结论

我必须重申一点,我是 TypeScript 粉丝,也在日常工作中使用它,但我确实认为它有很多缺陷,而且炒作有些过头了。Airbnb 声称 TypeScript 可以阻止 38%的错误。我非常怀疑这一精确的百分比数字。TypeScript 不会给已有的良好实践锦上添花。我还是得编写尽可能多的测试。你可能不相信,我编写的代码变多了,可能还得编写许多类型测试。我仍然会遇到意外的运行时错误。

TypeScript 提供了比较基础的类型检查,但健全性和运行时类型检查不是它的目标,这让 TypeScript 处于脚踩两条船的状态,一只脚踏上了更好的那艘,一只脚还呆在现在的破船上,真是不幸。

TypeScript 的亮点在于良好的 IDE 支持,比如说 vscode 里如果我们打错什么内容,就会获得视觉反馈。


vscode 中的 TypeScript 错误

使用 TypeScript 还可以增强重构能力,并且在对修改后的代码运行 TypeScript 编译器时,可以立即识别出代码中断(例如方法签名的更改)。

TypeScript 带来了良好的类型检查,并且绝对比没有类型检查器或仅使用普通的 eslint 要更好,但是我认为它能更进一步。另外对于我们这种想要更多能力的用户来说,它应该可以提供足够多的编译器选项才是。

英文原文:Is TypeScript Worth It?

链接: https://www.fly63.com/article/detial/8355

用TypeScript弥补Elm和JavaScript之间的差距

近些日子,我使用了新语言编程,从JavaScript,切确地说是Elm,转成TypeScript。在本文中,我将继续深挖一些我非常喜欢的TypeScript特性。

Typescript 和 Javascript之间的区别

TypeScript 和 JavaScript 是目前项目开发中较为流行的两种脚本语言,我们已经熟知 TypeScript 是 JavaScript 的一个超集,但是 TypeScript 与 JavaScript 之间又有什么样的区别呢?

Nerv_一款类 React 前端框架,基于虚拟 DOM 技术的 JavaScript(TypeScript) 库

Nerv_是一款由京东凹凸实验室打造的类 React 前端框架,基于虚拟 DOM 技术的 JavaScript(TypeScript) 库。它基于React标准,提供了与 React 16 一致的使用方式与 API。

TypeScript_TS系列之高级类型

交叉类型:将多个类型合并为一个类型、联合类型:表示取值可以为多种类型中的一种、混合类型:一个例子就是,一个对象可以同时做为函数和对象使用,并带有额外的属性、类型断言:可以用来手动指定一个值的类型

TypeScript 在 JavaScript 的基础上的改动

在做比较大的,多人合作的项目的时候,TypeScript会更加地适合,这得益于它的可读性,面向对象性以及易于重构的特点。但如果只是自己做小程序,不需要太多人参与的时候,JavaScript则会更加简单。

5分钟了解TypeScript

有两种方式安装TypeScript,如何创建第一个TypeScript文件,在TypeScript中,可以使用interface来描述一个对象有firstName和lastName两个属性,TypeScript支持JavaScript的新功能,其中很重要的一个功能就是基于类的面向对象编程

如何编写 Typescript 声明文件

使用TypeScript已经有了一段时间,这的确是一个好东西,虽说在使用的过程中也发现了一些bug,不过都是些小问题,所以整体体验还是很不错的。有关TypeScript声明类型声明相关的目前就总结了这些比较常用的

谷歌为何会选用TypeScript?

谷歌在很早之前就张开双臂拥抱 Web 应用程序,Gmail 已经发布 14 年了。当时,JavaScript 的世界是疯狂的。Gmail 工程师不得不为 IE 糟糕的垃圾回收算法捏一把汗,他们需要手动将字符串文字从 for 循环中提取出来,以避免 GC 停顿

为什么要学习Typescript 语言呢?Typescript 开发环境安装

TypeScript是一种由微软开发的自由和开源的编程语言。它是JavaScript的一个超集,TypeScript是JavaScript类型的超集,它可以编译成纯JavaScript。TypeScript可以在任何浏览器、任何计算机和任何操作系统上运行,并且是开源的。

使用TypeScript两年后-值得吗?

差不多两年前,我在一个创业团队中开始了一个全新的项目。用到的全都是类似Microservices,docker,react,redux这些时髦的东西。我在前端技术方面积累了一些类似的经验

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!