原文标题:ECMAScript proposal: Type Annotations
ECMAScript 关于类型注解的提案已进入 stage1,阿林看到了原文后觉得很惊讶,因为原文表达的意思是 tc39 是真的想把静态类型检查这样的功能写进 JS 这门语言里,而不是像现在这样的在开发阶段用 TypeScript,然后再编译成健壮的 JS。
要知道,涉及到语言底层的改动,要考虑的兼容性、历史包袱、性能等问题,可不是一个小工作,这正是阿林很惊讶的原因。
在阿林的认知里,一个项目的代码能正常运行,但是如果非要吃饱了撑去做优化或者做重构,那就说明这个项目的架构或者设计真的很烂,可维护性和可延展性很差,不足以支持这个项目后续的开发(或者说后续开发起来效率很低)。
那么大到语言的层面,也许 JS 真的遇到了一些瓶颈,需要逐渐从动态弱类型语言,逐渐转变到既支持动态弱类型,也支持静态强类型。
这样的转变一定是向着好的方向去发展,毕竟谁也不喜欢吃饱了撑干费力不讨好的事,我们这些底层开发者如此,那些大佬们同样如此,既然他们非常认真地去设计和讨论这个提案,是有一定原因的,这些原因原文有介绍。
原文详细地介绍了这个提案目前的状况、动机和一些具体内容,讨论了某些 TypeScript 语法或特性不在考虑纳入的范围以及一些有待商榷的内容,回答了一些开发者们关于这个提案的问题,原文大纲可以总结成如下图:
如果这个提案顺利推进,未来的 ECMAScript 可能会包含部分 TypeScript 语法。
阿林觉得本文很有参考意义,就机翻加修改,翻译了本文,分享给想要了解 JS 这门语言最新资讯的朋友们,下面是正文。
本文档自 2022 年 3 月的 TC39 全会讨论以来没有更新过。细节将在未来几天内发生变化。
ECMAScript 提案:类型注解
这个提案的目的之一是使开发者能够在他们的JavaScript代码中添加类型注解,允许这些注解被一个 JavaScript 外部的类型检查器检查。在运行时,JavaScript引擎会忽略掉这些注解。
这个提议的另一个目的是让开发者能够运行用 TypeScript、Flow 和其他静态类型的 JavaScript 超集编写的程序,而不需要转译。
提案状况
目前处于阶段1
作者:
- Gil Tayar
- Daniel Rosenwasser (Microsoft)
- Romulo Cintra (Igalia)
- Rob Palmer (Bloomberg)
- …还有一群贡献者,详见 仓库贡献历史.
负责人:
- Daniel Rosenwasser (Microsoft)
- Romulo Cintra (Igalia)
- Rob Palmer (Bloomberg)
提案动机
在过去的十年中,静态类型检查的案例已经被证明是相当成功的。微软、谷歌和 Facebook 分别发布了TypeScript、Closure Compiler 和 Flow。它们都是对 JavaScript 进行增强,以获得生产力的提高,就像其他静态类型语言一样,包括在早期发现错误,以及强大的编辑器工具(代码提示)。
就 TypeScript、Flow 和其他语言而言,这些 JavaScript 的变体为在 JavaScript 中声明和使用类型带来了方便的语法。这种语法大多不影响运行时的语义,而且在实践中,将这些变体转换为普通 JavaScript 的大部分工作都是擦除类型。
社区使用和需求
在 2020 年和 2021 年的JS状态调查中,静态类型化是最需要的语言功能。
此外,TypeScript 目前在 GitHub 的 State of the Octoverse 中被列为第四大最常用的语言,在 Stack Overflow 的年度开发者调查中,它自2017年以来一直被列入最受欢迎的前4种语言和最常用的10种语言。
JavaScript 构建和编译的趋势
类型语法在 JavaScript 中的兴起与下层编译(有时称为 “转译”)的兴起相吻合。随着 ES2015 的标准化,JavaScript 开发者看到了精彩的新功能,但由于支持旧版浏览器的限制,他们无法立即使用。例如,一个箭头函数可以为开发者提供工效,但不能在每个终端用户的机器上运行。因此,Traceur、TypeScript 和 Babel 等项目通过将 ES2015 代码重写成可在旧版运行时运行的等效代码来填补这一空白。
因为类型语法在 JavaScript 中没有得到原生支持,所以必须有一些工具在运行任何代码之前删除这些类型。对于TypeScript 和 Flow 这样的类型系统来说,将类型清除步骤与语法降级步骤结合起来是有意义的,这样用户就不需要运行单独的工具。最近,一些捆绑器甚至开始做这两件事。
但随着时间的推移,我们预计开发人员对降级编译的需求将会减少。常青的浏览器已经成为常态,而在后端,Node.js和 Deno 使用了非常新的 V8 版本。随着时间的推移,对于许多 TypeScript 用户来说,编写代码和运行代码之间唯一必要的步骤就是抹去类型注释。
构建步骤为编写代码增加了另一层关注。例如,确保构建输出的新鲜度,优化构建的速度,以及管理给调试带来便利的 sourcemaps ,这些都是 JavaScript 最初避开的问题。这种简单性使得 JavaScript 更加平易近人。
这个提案将减少对构建步骤的需求,这可以使一些开发设置变得更加简单。用户可以简单地运行他们编写的代码。
在 JSDoc 中写类型注释的局限性
虽然构建工具并不难用,但对于许多开发者来说,它们是另一个入门障碍。这也是 TypeScript 团队花精力支持在JSDoc 注释中表达类型的部分原因。JSDoc 注释在 JavaScript 社区有一些记录类型的先例,这些类型被 所利用。
这种注释惯例经常出现在构建脚本、小型 Web 应用程序、服务器端应用程序和其他地方,在这些地方添加构建工具的成本/收益权衡太高。即使 TypeScript 不提供类型检查诊断,注释惯例仍然在编辑器功能中被利用,因为TypeScript 为底层的 JavaScript 编辑体验提供动力。
下面是一个基于 JSDoc 的类型语法的例子,来源链接。
/**
* @param {string} p1 - A string param.
* @param {string=} p2 - An optional param (Closure syntax)
* @param {string} [p3] - Another optional param (JSDoc syntax).
* @param {string} [p4="test"] - An optional param with a default value
* @return {string} This is the result
*/
function stringsStringStrings(p1, p2, p3, p4="test") {
// TODO
}
对比一下,下面是本提案所启用的等效的 TypeScript 语法。
function stringsStringStrings(p1: string, p2?: string, p3?: string, p4 = "test"): string {
// TODO
}
JSDoc 注释通常更加冗长。除此之外,JSDoc 注释只提供了 TypeScript 支持的功能集的一个子集,部分原因是很难在 JSDoc 注释中提供表达式语法。
尽管如此,基于 JSDoc 的语法仍然是有用的,而且在 J