关于TS的思考

JS 是一门脚本语言,也是一个非常灵活的语言。

灵活是一把双刃剑,一方面他让作者可以写更少的代码,一方面又增加读者理解代码的难度。

随着时代的发展,JS 的使用量逐渐扩大。这时一个能帮助我们写出更容易维护的 JS 代码的工具就显得非常必要了。

时代催生了两个知名项目来实现这个目标,一个是 Facebook 的 Flowjs,一个是 Microsoft 的 TS。

他们选择了相似但又有区别的技术路线。

  • Flowjs 倾向于保留 JS 的所有灵活性,让工具去适应这种灵活性。
  • TS 则倾向于先限制部分 JS 的灵活性,并在工具稳定支持的前提下逐步放开限制。

在多年竞争后,TS 赢得了市场的认可,而 Flowjs 逐渐淘汰,这也意味着从商业产品角度,TS 的路线是比 Flowjs 更正确的。

目前仍有部分人认为 TS 限制太多,他们倾向于编写传统的 JS 代码。那其实本质原因并不是 TS 不够好,而是 TS 给他们带来的功能并不足以说服他编写额外的代码。

TS 设计理念

TS 的设计理念是务实,这点我是非常认可的。

务实设计点1:宽松的类型校验

  1. var a: 动物[] = []
  2. var b: 猫[] = a // 将“动物[]”转为“猫[]”,是正确的转换吗?

有一些人认为 TS 的类型不够严谨,于是就做了一些 TS 改版,以使得校验更“正确”,但事实证明这些项目都失败了。

根本原因是:除非直接运行代码,否则我们是无法 100% 准确推测类型是否正确的。

从编译器角度,我们分析代码可以得到四种结论:

  • 代码一定是对的
  • 代码一定是错的
  • 代码可能是对的,也可能是错的

对于前两者场景,编译器一定需要报错或不报。而对于第三个场景,编译器要不要报错,取决于设计者的权衡。

如果类型校验做到绝对严谨,意味着对于“代码可能是对的”也会报错,而这无疑增加了用户排错的成本。

TS 的权衡宗旨是:

  1. 不要对很可能是对的代码报错,这会让用户厌恶。
  2. 编译器报错的代码,最好真的就是一个 BUG,这会让用户喜欢上 TS。
  3. 如果编译器报错了,一定要留一条后路,方便用户解决报错。

务实设计点2:分发条件类型

如果不是 TS 的深度用户,可能看不懂“分发条件类型”。
但 TS 的巧妙就在用户可能正在使用“分发条件类型”,但又不需要知道“分发条件类型”是什么。

分发条件类型是指条件类型在判断填充为联合类型时的泛型时,会有特殊处理。
这种处理可能导致有些场景的无规律或难以理解,但在多数场景下,他都符合用户预期。