TS最终编译为JS,它是如何实现JS原生不支持的各类特性的?
TS编译为JS的实现逻辑与上层语言特性实现原理
TS编译的核心流程
TS的整个编译过程完全在代码运行前完成,核心分为4个阶段:
- 词法/语法分析:编译器读取TS源码,先把字符流拆分为一个个最小语法单元(token),再组装为抽象语法树(AST),TS专属的类型标注、
interface、enum、装饰器等语法都会在这一步被完整识别。 - 静态类型校验:这是TS类型系统生效的核心阶段,编译器会遍历整个AST,按照TS的类型规则逐节点校验,比如给
string类型变量赋值数值、调用对象不存在的属性这类错误,都会在这一步抛出提示,校验不通过就不会进入后续的转译环节。注意:类型校验完全是编译时行为,不会生成任何可运行的JS代码。 - 代码转译:校验通过后,编译器会把AST中的TS专属语法做擦除或者等价转换:
比如类型标注const name: string = 'Jack'会直接擦除类型,输出为const name = 'Jack';
枚举enum Status { Success, Fail }会被转成符合JS规范的对象映射实现;
要是配置了低版本JS输出目标,async/await这类新语法也会被转成基于Promise的兼容实现。 - 输出JS文件:最终输出的代码完全符合指定版本的ECMAScript规范,可以直接在浏览器、Node.js等JS runtime中运行。
上层语言实现底层无原生支持特性的通用逻辑
不止是TS和JS,所有“上层语言编译为下层语言”的场景,实现下层没有的特性基本都是两种思路:
- 编译时处理,运行时完全擦除
这类特性不需要在运行时生效,全部逻辑都放在编译阶段完成,下层语言完全不需要感知到特性的存在。最典型的就是TS的类型系统,所有类型检查都在编译时做完,生成的JS代码里没有任何类型相关的逻辑,自然不需要JS原生支持类型系统。 - 转译为下层语言的等价实现
对于需要在运行时生效的特性,编译器会把上层语法糖转成下层语言原生支持的等价代码。比如TS的类属性readonly修饰符,编译时会做赋值校验,运行时如果是对象属性就会转成Object.defineProperty设置writable: false的原生实现;再比如旧版TS要把class语法转成ES5可运行的代码,编译器会自动生成构造函数加原型继承的等价JS逻辑,本质就是用下层已有的能力封装出上层特性的表现效果。
内容的提问来源于stack exchange,提问作者Hey Itsme
相关产品推荐
相关产品推荐

