当前位置: 首页 > 科技观察

原生JS也会支持类型注解吗?

时间:2023-03-14 23:39:02 科技观察

大家好,我是Kason。在布达佩斯举行的2022JSConf[1]会议上,tc39[2](ES标准委员会)成员“GilTayar”介绍了一个尚处于阶段1的提案——类型注解,旨在让原生JS支持类型注解.GilTayar表示,如果提案通过,很多.ts文件在将后缀改为.js后可以直接在浏览器中运行。一个tc39提案通常会经历5个阶段:第0阶段:提出。第一阶段:接受审查。第二阶段:规范基本完成。第三阶段:等待实现。阶段4:纳入语言标准。因此,TypeAnnotations目前还处于“接受考虑”的状态。不过,提案的发起人“GilTayar”对这个提案的通过很有信心。在这篇文章中,我们将谈谈这个提案的相关内容。为什么需要原生类型注解?根据20和21年JS[3]的状态统计,“静态类型”以高票被评为“JS中最缺乏的功能”。同时,在Github报告[4]中,TS被列为“第四大最常用语言”。因此,对于前端工程师来说,“类型注解”的需求量很大。那么,既然TS已经有了,为什么还需要原生JS来支持“类型注解”呢?一般来说,“开发者编写的源代码”和“线上生产环境代码”之间需要进行“代码编译”。“代码编译”主要包括两个步骤:降级编译(包括高级语法到低级语法的转换,高级方法的polyfill)。代码翻译(例如缩小、混淆、tree-shaking、类型擦除)。所谓“类型擦除”是指擦除代码中的“类型注解”,使其符合原生JS规范代码,例如://擦除前的函数add(a:number,b:number):number{returna+b;}//擦除后functionadd(a,b){returna+b;}随着时间的推移,各大浏览器的兼容性越来越好,“第一步”可以预见以后重要性逐渐下降。对于TS开发者来说,从“源代码”到“线上生产环境代码”可能只需要“类型擦除”。如果原生JS支持“类型注解”,就可以省略“类型擦除”对应的编译过程,让代码更容易在宿主环境中执行。与TS的关系本提案的目的不是从头开始,独立实现一套原生的JS类型注解。相反,与“TS团队”合作,提出一套合适的规范。新规范与“TS规范”的关系类似于下图:一方面,TypeAnnotations提案借鉴了TS的很多特性,也就是图中相交的部分。你可以去grammar-conventions[5]查看规范当前定义的类型。另一方面,TS快速迭代并快速产生新功能。而TypeAnnotations作为JS语言的一部分,迭代会比较保守,所以TypeAnnotations不支持TS中的一些特性。此外,TS中的一些结构(如Enums、Namespaces)具有运行时语义,TypeAnnotations将不支持它们。这些是TS中存在而TypeAnnotations中不存在的部分。最后,TypeAnnotations设计的初衷并不是为了和TS强绑定,只是提供一套类型规范。开发者编写代码时的“类型检查”仍然是由各种类型检查器(如TS、Flow)完成的。因此,TypeAnnotations中有一些特性目前是TS没有定义的,这也是为了规范更广泛的适用性考虑,也就是图中有TypeAnnotations而TS没有的部分。这部分特性需要TS后续实现,这也是TypeAnnotations与TS团队合作的原因之一。对开发者意味着什么如果TypeAnnotations最终出现在ES20xx版本中,那时候开发者编写代码的步骤是:选择一个合适的类型检查器(比如TS),这个类型检查器需要完全遵循TypeAnnotations规范(不是它自己的规范,例如TS规范)。使用类型声明编写本机JS代码。类型检查器将检查类型错误并给出错误或提示。对于下面的原生JS代码,如果开发者传入错误的类型,JS会报错吗?functionadd(a:number,b:number):number{returna+b;}//传错类型参数add('KaSong',123);答案是不。类型注释只是一组规范,由各种类型检查器强制执行。JS宿主环境(如浏览器)在执行“带有类型声明的JS代码”时会忽略类型声明。小结有同学可能会问:是否有必要提出一个nativetypespecification,以减少编译时的“类型擦除”步骤?即使在TypeAnnotations落地之后,开发人员在上线前压缩代码时,“类型擦除”也将是“代码压缩”的职责之一。从这个角度来看,它甚至没有减少编译时的工作。那么是否有必要提出原生类型规范呢?前端的开发其实就是一个“努力编译过程”的过程。比如代码需要在编译时降级,需要polyfill?随着IE11的下线,主流浏览器纷纷跟进标准的落地,降级和polyfill的需求逐渐减少。再比如,代码需要打包吗?随着ESM规范的实施,目前至少在开发环境中,代码不需要打包(使用Vite)。TypeAnnotations的出现是顺应“努力编译过程”潮流的产物。从这个角度来说,还是很有必要的。参考资料[1]布达佩斯2022JSConf:https://www.youtube.com/watch?v=SdV9Xy0E4CM&list=PL37ZVnwpeshGuMZrOZzEo8QLBjjpbtBGm&index=2。[2]tc39:https://github.com/tc39。[3]JS状态:https://stateofjs.com/en-us/。[4]Github报告:https://octoverse.github.com/。[5]语法约定:https://tc39.es/proposal-type-annotations/grammar.html#grammar-conventions。