引言
在布达佩斯2022 JSConf会议上, tc39 (ES标准委员会)成员 Gil Tayar 介绍了一份当前仍处于 stage 1 阶段的提案 —— Type Annotations ,意在让原生 JS 支持类型注解。
换句话说,如果提案通过,很多 .ts 文件将后缀改为 .js 后就能直接在浏览器中运行。
一份 tc39 提案通常会经历5个阶段:
stage 0:被提出 stage 1:接受审议 stage 2:规范基本完成 stage 3:等待被实现 stage 4:纳入语言标准中所以 Type Annotations 当前仍处于 接受审议 的状态。
但是提案发起者 Gil Tayar 对这份提案的通过很有信心,本文我们来聊聊这份提案的相关内容。
为什么需要原生类型注解?
根据20年、21年 state of JS 的统计, 静态类型 高票当选 JS中当前最欠缺的功能 。
同时,在 Github报告 中, TS 被列为 第四大最常用的语言
所以,对前端工程师来说, 类型注解 需求很大。
那么,既然已经有了 TS ,为什么还需要原生 JS 支持 类型注解 呢?
通常来说,从 开发者编写的源代码 到 线上生产环境代码 间需要经过 代码编译 。
代码编译 主要包括两个步骤:
降级编译(包括高级语法转换为低级语法,高级方法的 polyfill ) 代码转译(比如压缩、混淆、tree-shaking、类型擦除)所谓 类型擦除 ,是指擦除代码中的 类型注解 ,让其变成符合原生 JS 规范的代码,比如:
// 擦除前 function add(a: number, b: number): number { return a + b; } // 擦除后 function add(a, b) { return a + b; }
随着时间的推移,各主流浏览器兼容性越来越好, 步骤1 在可预见的未来重要性会逐渐降低。
对于 TS 开发者,从 源代码 到 线上生产环境代码 间可能只需要 类型擦除 。
如果原生 JS 支持 类型注解 ,就能省去 类型擦除 对应的编译流程,让代码更容易在宿主环境执行。
和TS的关系
这份提案的目的,并不是另起炉灶,独立实现一套原生 JS 的类型注解。而是与 TS团队 合作,提出一套合适的规范。
新的规范与 TS规范 的关系类似下图:
一方面, Type Annotations 提案从 TS 中借鉴了很多特性,这就是图中相交的部分。
你可以到 grammar-conventions 看到规范当前定义的类型
另一方面, TS 迭代速度很快,新的特性产出很快。而 Type Annotations 作为 JS 语言的一部分,迭代会更加保守,所以 TS 中一些特性在 Type Annotations 中并不支持。
此外, TS 中一些结构(比如 Enums 、 Namespaces )存在运行时的语义, Type Annotations 也不会支持。
这些就是 TS 中存在,而 Type Annotations 中不存在的部分。
最后, Type Annotations 设计的初衷并不是与 TS 强绑定,而仅仅是提供一套类型规范,开发者编写代码时的 类型检查 还是由各种类型检查器(比如 TS 、 Flow )实现。
所以, Type Annotations 还有一部分特性是 TS 当前未定义的,这也是为了规范更广泛的适用性考虑的,也就是图中 Type Annotations 存在,而 TS 不存在的部分。
这部分特性需要 TS 后续实现,这也是为什么 Type Annotations 要与 TS 团队合作的一大原因。
对开发者意味着什么
如果 Type Annotations 最终出现在 ES20xx 版中,届时开发者编写代码的步骤是:
选择合适的类型检查器(比如 TS ),这个类型检查器需要完全遵循 Type Annotations 规范(而不是自己的规范,比如 TS 规范) 编写带类型声明的原生 JS 代码 类型检查器会检查类型错误,并给予报错或提示对于如下原生 JS 代码,如果开发者传入了错误的类型, JS 会报错么?
function add(a: number, b: number): number { return a + b; } // 错误的类型传参 add('KaSong', 123);
答案是:不会。
Type Annotations 仅仅是一套规范,该规范由各种类型检查器执行。
JS 的宿主环境(比如浏览器)在执行 带类型声明的JS代码 时,会忽略类型声明。
总结
有同学可能会问:就为了减少编译时 类型擦除 这一步,就提出原生类型规范,有必要么?
甚至当 Type Annotations 落地后,开发者上线前在进行代码压缩时, 类型擦除 也会作为 代码压缩 的职责之一。
从这个角度看,甚至没有减少编译时的工作量。
所以提出原生的类型规范,有必要么?
前端的发展实际是一个 努力去编译时流程 的过程。
比如,编译时代码需要降级,需要 polyfill ?随着 IE11 停止服务,主流浏览器纷纷跟进标准落地,降级与 polyfill 的需求逐渐变少。
再比如,代码需要打包?随着 ESM 规范落地,在当前,至少在开发环境中代码已经不需要打包(使用 Vite )。
Type Annotations 的出现,就是遵循 努力去编译时流程 这一趋势的产物。
从这个角度看,还是很有必要的。
以上就是原生JS以后也支持类型注解意义的详细内容,更多关于原生JS支持类型注解的资料请关注其它相关文章!