TypeScript 编译原理
理解 TypeScript 编译器工作流程有助于排查编译异常与优化构建性能,下面梳理核心流程。
编译流程概览
TypeScript
.ts 源码 → 词法分析 → 语法树(AST) → 类型检查 → 代码发射 → .js 输出
词法分析(Scanner)
将源码分解为 Token 序列:
TypeScript
// 源码
let x: number = 42;
// Token 序列
// [Keyword(let), Identifier(x), Punctuation(:), Keyword(number), Punctuation(=), NumericLiteral(42), Punctuation(;)
词法分析器不关心语法正确性,只负责识别基本单元。
语法树生成(Parser)
将 Token 序列解析为抽象语法树(AST):
TypeScript
// AST 结构(简化)
{
kind: "VariableStatement",
declarationList: {
declarations: [{
name: { kind: "Identifier", text: "x" },
type: { kind: "NumberKeyword" },
initializer: { kind: "FirstLiteralToken", text: "42" }
}]
}
}
可通过 AST Viewer 工具查看完整结构。
类型检查(Checker)
遍历 AST 进行类型推导与校验:
- 类型推断:根据声明与赋值推导变量类型
- 类型比对:检查赋值/参数/返回值是否符合类型约束
- 错误报告:记录类型不兼容/缺失属性等错误
TypeScript
let x: number = "hello"; // ❌ 类型不兼容
// Checker 发现:
// - x 声明为 number
// - "hello" 是 string
// - string 不能赋值给 number
结构化类型系统
TypeScript 使用结构化类型(Duck Typing),不关心类型名称,只看结构:
TypeScript
interface A { x: number; y: string; }
interface B { x: number; y: string; }
let a: A = { x: 1, y: "hello" };
let b: B = a; // ✅ 结构相同,可赋值
代码发射(Emitter)
将 AST 转换为目标 JavaScript 代码:
TypeScript
// 输入
class Greeter {
greet() { console.log("Hello"); }
}
// 输出(target: ES5)
var Greeter = /** @class */ (function () {
function Greeter() {}
Greeter.prototype.greet = function () {
console.log("Hello");
};
return Greeter;
}());
发射选项
| 选项 | 说明 |
|---|---|
target | 输出 JS 版本(ES5/ES2015/ESNext) |
module | 模块格式(commonjs/esnext/amd) |
declaration | 生成 .d.ts 声明文件 |
sourceMap | 生成 .js.map 源码映射 |
outDir | 输出目录 |
编译器 API
TypeScript 暴露编译器 API,可用于代码分析与转换:
JSON
import ts from "typescript";
const source = `let x: number = 42;`;
const sourceFile = ts.createSourceFile("test.ts", source, ts.ScriptTarget.Latest);
// 遍历 AST
function visit(node: ts.Node) {
if (ts.isVariableDeclaration(node)) {
console.log("Found variable:", (node.name as ts.Identifier).text);
}
ts.forEachChild(node, visit);
}
visit(sourceFile);
增量编译
TypeScript 支持增量编译(--incremental),缓存上次编译信息加速后续编译:
text
{
"compilerOptions": {
"incremental": true,
"tsBuildInfoFile": "./.tsbuildinfo"
}
}
要点总结
- 编译流程:词法分析 → 语法树 → 类型检查 → 代码发射
- Scanner 分词,Parser 生成 AST,Checker 校验类型,Emitter 输出 JS
- TypeScript 使用结构化类型系统,结构相同即可赋值
- 编译器 API 可用于自定义代码分析与转换工具
- 增量编译(
--incremental)缓存信息加速重复编译
📝 发现内容有误?点击此处直接编辑