大家好,我是 ssh。TypeScript 团队在深夜突然发了一条推,神秘兮兮说:“如果我们可以直接在 JavaScript 中支持类型,会怎么样?”。
他们在评论区说:“类型作为注释”的提案意味着浏览器可以直接运行通过了 TS 检查的代码(即使它们没有做任何类型检查)。这意味着更好的编辑体验和更快的迭代。
这是一个很让人兴奋的想法,接下来我们具体看看这个提案的内容。
这是一个新的 stage0 的语法提案,暂时还未提交给 TC39。github 的仓库地址是 https://github.com/giltayar/proposal-types-as-comments
背景
我们团队最近在 JavaScript 领域看到的一个趋势是,需要更快的迭代时间和减少构建步骤。换句话说,“更快、更简单”。
在某种程度上,这已经发生了。多亏了浏览器的成功,开发人员通常可以避免编译较新版本的JavaScript以在较旧的 runtime上运行。在某种程度上,构建也是如此 —— 大多数浏览器都内置了对 module 的支持,因此构建渐渐成为了一个优化步骤而不是必要步骤。这种情况下,TypeScript 如何跟进呢?
如果我们回到2012年,TypeScript首次发布的时候,JavaScript的世界就大不相同了!一些浏览器经常更新,但另一些不会。我们还不清楚Internet Explorer的古老版本会持续多久,这导致构建工具和编译器等工具大行其道。在向JavaScript添加构建步骤的时代,TypeScript能够蓬勃发展——毕竟,如果你需要编译JavaScript,为什么不也顺便编译你的类型呢?但是,如果我们上面提到的这些趋势继续发展,编译类型可能是编写 TypeScript 代码到运行之间的唯一步骤,我们不想成为阻碍良好开发体验的人!
在某些方面,我们的 JavaScript 支持弥补了这一差距,如果您使用像Visual Studio或Visual Studio Code这样的编辑器,可能已经见过 JSDoc 形式添加类型注释:
/** * @param a {number} * @param b {number} */ function add(a, b) { return a + b; }
因为这些只是注释,它们根本不会改变代码的运行方式——它们只是一种文档形式,但TypeScript利用了它们,通过代码补全、自动重构等方式为您提供更好的JavaScript编辑体验。甚至可以通过在文件顶部添加 // @ts check
注释来添加类型检查[1],或者通过TypeScript编译器,开启 checkJs
选项来运行这些文件。这个特性使得在不需要构建步骤的情况下就可以获得一部分的TypeScript体验,您可以将其用于小型的脚本、基本网页和 Node.js服务端代码等等。
不过,您会注意到这有点冗长,失去了 TypeScript 写类型的简洁性。
如果我们全都要呢?
如果我们可以有一些像TypeScript这样的语法,但在JavaScript中完全被忽略——有点像注释。
function add(a: number, b: number) { return a + b; }
我们的团队相信这里有很大的潜力,本月我们希望将其作为提案提交[2]给ECMAScript标准委员会TC39!
如何工作?
当我们被问到“JavaScript什么时候能拥有类型?”,我们回答的很犹豫。在过去,如果你问开发人员他们对JavaScript中的类型有什么想法,你会得到很多不同的答案。一些人认为类型应该被完全忽略,而另一些人则认为它们应该具有某种意义——可能是它们应该执行某种运行时验证,或者它们应该作为引擎优化的提示等等。但在过去几年里,我们看到人们更倾向于一种与TypeScript的发展方向一致的设计,即类型在运行时被完全忽略且可擦除。现在我们可以自信的提出“类型作为注释”的提案了。
这个提案的想法是[3],可以开创一组语法,JavaScript 完全忽视它,但TypeScript、Flow等工具可以使用这些语法。这使我们能够保留您喜欢的TypeScript里的内容——它的类型检查和编辑体验,同时消除开发中需要的构建步骤。
因此,在编写和运行代码时,工具链看起来会有些不同。
与此同时,编写代码和类型检查将保持不变。开发人员可以在支持TypeScript的编辑器中获得即时类型检查反馈,在命令行里运行TypeScript,将TypeScript添加到CI任务中。最大的区别是,因为我们不需要构建步骤,所以我们将大大降低JavaScript开发人员的入门门槛,让他们体验类型和优秀工具的强大功能。
要实现这一点,JavaScript只需为变量和函数上的类型注释、可选性修饰符(?
)等添加语法对于参数和类成员、类型声明(interface
和type
别名)和类型断言运算符(as
和!
)——所有这些都不会影响周围代码的运行方式。
同时也支持可见性修饰符(例如public
、private
和protected
);然而, enum
、namespace
将参数属性不在本提案的范围内,因为它们具有可见的运行时行为。根据反馈,这些特性可以作为单独的ECMAScript特性提出,但我们当前的目标是支持TypeScript的一些大子集,我们认为这可能是JavaScript的一个很有价值的补充。
通过这一突破,我们为类型检查器提供了创新的空间。这确实意味着引擎会很顺利地运行代码,但我们相信类型检查器可以(也应该)是规范性的,并实施比运行时更严格的约束。结合起来,这就形成了一种类型语法,可以跨不同的检查器进行定制,或者如果有人认为他们对TypeScript或任何其他类型检查器不满意,也可以删除掉。
这不是什么?
值得一提的是,这个提议不是什么。
我们的团队没有提出把 TypeScript 的类型检查器放到每个浏览器和JavaScript运行时中 —— 我们也没有提出要在浏览器中放入的任何新的类型检查器。我们认为这样做会导致JavaScript和TypeScript用户的一系列问题,例如运行时性能、兼容性问题以及扼杀类型领域的创新。
相反,我们只是提出了与TypeScript兼容并受其驱动的语法,任何类型检查器都可以使用它,但JavaScript引擎会跳过它。我们相信这种方法对每个人来说都是最有前途的,并将继续允许TypeScript、Flow和其他人继续创新。
接下来?
鉴于所有这些,我们计划在即将到来的2022年3月TC39全体会议上提交 Stage 1[4] 的提案。我们将在这项提案的共同倡导者,彭博社的Rob Palmer[5]和Igalia的Romulo Cintra[6]的支持和指导下完成这项工作。
达到第1阶段意味着标准委员会认为支持类型语法对于ECMAScript是值得考虑的。这并不是一件肯定会引起轰动的事情——委员会内部有许多有价值的观点,我们确实期待一些怀疑的声音。这样的提案会得到大量反馈和适当的审查。这一过程可能涉及大量的设计变更,可能需要数年时间才能产生结果。
但如果我们完成了这一切,我们就有机会对JavaScript世界做出最有影响力的改进之一。我们对此感到兴奋,希望你们也一样。
如果您有兴趣了解更多关于细节和当前方向的信息,请前往提案的仓库[7]。我们期待着听到你的想法!
最后,TypeScript团队和champions group要感谢所有从事现有技术[8]工作的人,以及那些伸出援助之手帮助进行评论的撰稿人,尤其是帮助推动这项工作的Gil Tayar[9]。我们非常感激能成为这样一个充满激情的社区的一部分!
参考资料
[1]
类型检查: https://www.typescriptlang.org/docs/handbook/intro-to-js-ts.html
[2]
作为提案提交: https://github.com/giltayar/proposal-types-as-comments
[3]
这个提案的想法是: https://github.com/giltayar/proposal-types-as-comments
[4]
Stage 1: https://tc39.es/process-document/
[5]
Rob Palmer: https://github.com/robpalme
[6]
Romulo Cintra: https://github.com/romulocintra
[7]
请前往提案的仓库: https://github.com/giltayar/proposal-types-as-comments/
[8]
现有技术: https://github.com/giltayar/proposal-types-as-comments#prior-art
[9]
Gil Tayar: https://github.com/giltayar/