基于 TypeScript 官方源码的编译器架构剖析
2026-03-26 | 50 页技术深度解读
TypeScript 是微软开发的开源编程语言,为 JavaScript 添加了可选的静态类型和基于类的面向对象编程。
核心特性:
项目规模:
| 阶段 | 输入 | 输出 | 职责 |
|---|---|---|---|
| Scanner | 源码字符串 | Token 流 | 词法分析 |
| Parser | Token 流 | AST | 语法分析 |
| Binder | AST | Symbol 表 | 符号绑定 |
| Checker | AST + Symbol | Type 信息 | 类型检查 |
| Emitter | AST + Type | JavaScript | 代码生成 |
职责:将源代码字符串转换为 Token 流
核心功能:
源码位置:src/compiler/scanner.ts
// scanner.ts 核心接口
function createScanner(
sourceText: string,
languageVersion: ScriptTarget
): Scanner {
let pos = 0;
let token: SyntaxKind;
let tokenValue: string;
return {
scan() {
// 跳过空白和注释
while (isWhiteSpace(pos)) pos++;
// 识别 token 类型
const char = sourceText[pos];
if (isIdentifierStart(char)) {
return scanIdentifier();
}
if (isDigit(char)) {
return scanNumber();
}
// ... 其他 token 类型
},
getTokenText() { return tokenValue; },
getToken() { return token; }
};
}
// SyntaxKind 枚举(部分)
const enum SyntaxKind {
// 字面量
StringLiteral = 1,
NumericLiteral = 2,
NoSubstitutionTemplateLiteral = 3,
// 标识符
Identifier = 4,
// 关键字
FunctionKeyword = 5,
ClassKeyword = 6,
InterfaceKeyword = 7,
TypeKeyword = 8,
ConstKeyword = 9,
// 操作符
PlusToken = 10,
MinusToken = 11,
AsteriskToken = 12,
// 标点符号
OpenParenToken = 13,
CloseParenToken = 14,
OpenBraceToken = 15,
CloseBraceToken = 16
}
职责:将 Token 流转换为抽象语法树(AST)
核心功能:
源码位置:src/compiler/parser.ts
// parser.ts 核心函数
function parseSourceFile(
fileName: string,
sourceText: string
): SourceFile {
// 1. 初始化 scanner
scanner = createScanner(sourceText);
nextToken(); // 读取第一个 token
// 2. 解析语句列表
const statements = parseList(
ParsingContext.SourceElements,
parseStatement
);
// 3. 创建 SourceFile 节点
return factory.createSourceFile(
statements,
/*flags*/ 0
);
}
function parseStatement(): Statement {
switch (token()) {
case SyntaxKind.FunctionKeyword:
return parseFunctionDeclaration();
case SyntaxKind.ClassKeyword:
return parseClassDeclaration();
case SyntaxKind.ConstKeyword:
case SyntaxKind.LetKeyword:
case SyntaxKind.VarKeyword:
return parseVariableStatement();
// ... 其他语句类型
}
}
AST 核心节点类型:
// 源文件(AST 根节点)
SourceFile
├── statements: Statement[] // 顶层语句数组
// 主要声明类型
├── FunctionDeclaration // 函数声明
├── ClassDeclaration // 类声明
├── InterfaceDeclaration // 接口声明
├── VariableStatement // 变量语句
├── ImportDeclaration // 导入声明
└── ExportDeclaration // 导出声明
// 表达式节点
Expression
├── Identifier // 标识符
├── CallExpression // 函数调用
├── BinaryExpression // 二元运算
└── ObjectLiteralExpression // 对象字面量
职责:为 AST 节点创建 Symbol,建立作用域链
核心功能:
源码位置:src/compiler/binder.ts(源码行数:2万+)
// binder.ts 核心函数(从源码提取)
export function bindSourceFile(
file: SourceFile,
options: CompilerOptions
): void {
// 1. 初始化绑定器状态
symbolCount = 0;
Symbol = objectAllocator.getSymbolConstructor();
// 2. 递归绑定节点
bind(file);
// 3. 延迟绑定 JSDoc 类型
delayedBindJSDocTypedefTag();
// 4. 记录符号数量
file.symbolCount = symbolCount;
}
function bind(node: Node): void {
// 根据节点类型执行绑定
switch (node.kind) {
case SyntaxKind.SourceFile:
bindSourceFile(node);
break;
case SyntaxKind.FunctionDeclaration:
bindFunctionDeclaration(node);
break;
// ... 其他节点类型
}
}
// binder.ts 中的符号声明函数
function declareSymbol(
symbolTable: SymbolTable,
parent: Symbol | undefined,
node: Declaration,
includes: SymbolFlags,
excludes: SymbolFlags
): Symbol {
const name = getDeclarationName(node);
// 检查符号是否已存在
let symbol = symbolTable.get(name);
if (!symbol) {
// 创建新符号
symbol = createSymbol(SymbolFlags.None, name);
symbolTable.set(name, symbol);
} else if (symbol.flags & excludes) {
// 符号冲突,报告错误
reportSymbolConflict(symbol, node);
symbol = createSymbol(SymbolFlags.None, name);
}
// 添加声明到符号
addDeclarationToSymbol(symbol, node, includes);
symbol.parent = parent;
return symbol;
}
// binder.ts 中的控制流节点
interface FlowNode {
flags: FlowFlags;
id: number;
node: Node;
antecedent: FlowNode | FlowNode[];
}
const enum FlowFlags {
Start = 1 << 0,
Unreachable = 1 << 1,
BranchLabel = 1 << 2,
Assignment = 1 << 3,
Condition = 1 << 4,
Call = 1 << 5,
ArrayMutation = 1 << 6,
SwitchClause = 1 << 7,
ReduceLabel = 1 << 8
}
// 用途:类型收窄、不可达代码检测
// 示例:if (typeof x === "string") { x.toUpperCase(); }
职责:类型检查、类型推导、错误报告
核心功能:
源码位置:src/compiler/checker.ts(源码行数:5万+,最大的文件!)
// checker.ts 核心函数(从源码提取)
export function createTypeChecker(
host: TypeCheckerHost
): TypeChecker {
// 核心数据结构
var globals = createSymbolTable();
var undefinedSymbol = createSymbol(
SymbolFlags.Property,
"undefined"
);
var globalThisSymbol = createSymbol(
SymbolFlags.Module,
"globalThis"
);
// 类型检查主函数
function checkSourceFile(file: SourceFile) {
forEachChild(file, checkNode);
}
return {
getTypeOfSymbol,
checkExpression,
getDiagnostics,
// ... 其他接口
};
}
// 类型推导示例
function inferType(
node: Expression,
context: Type
): Type {
// 1. 收集约束
const constraints = collectConstraints(node);
// 2. 求解类型变量
const solution = solveConstraints(constraints);
// 3. 实例化类型
return instantiateType(context, solution);
}
// 示例:推导数组类型
// const arr = [1, 2, 3];
// 推导过程:
// 1. 数组元素类型: number
// 2. 数组类型: number[]
// 示例:推导泛型参数
// function identity<T>(x: T): T { return x; }
// identity(42); // T 推导为 number
// 类型比较核心函数
function isTypeAssignableTo(
source: Type,
target: Type
): boolean {
// 1. 相同类型
if (source === target) return true;
// 2. any 类型
if (target.flags & TypeFlags.Any) return true;
// 3. 结构类型比较
if (isObjectLikeType(source) && isObjectLikeType(target)) {
return compareProperties(source, target);
}
// 4. 联合类型
if (source.flags & TypeFlags.Union) {
return every(type.types, t => isTypeAssignableTo(t, target));
}
// 5. 交叉类型
if (target.flags & TypeFlags.Intersection) {
return some(type.types, t => isTypeAssignableTo(source, t));
}
return false;
}
// 诊断系统
interface Diagnostic {
file: SourceFile;
start: number;
length: number;
messageText: string | DiagnosticMessageChain;
category: DiagnosticCategory;
code: number;
}
const enum DiagnosticCategory {
Warning = 0,
Error = 1,
Suggestion = 2,
Message = 3
}
// 错误示例
// Type 'string' is not assignable to type 'number'
// 错误代码: 2322
// 类别: Error
职责:将 TypeScript AST 转换为 JavaScript 代码
核心功能:
源码位置:src/compiler/emitter.ts
// emitter.ts 核心流程
function emitSourceFile(
sourceFile: SourceFile
): string {
const writer = createTextWriter();
// 遍历 AST 并生成代码
forEachChild(sourceFile, node => {
emitNode(node, writer);
});
return writer.getText();
}
function emitNode(node: Node, writer: TextWriter) {
switch (node.kind) {
case SyntaxKind.VariableDeclaration:
emitVariableDeclaration(node, writer);
break;
case SyntaxKind.FunctionDeclaration:
emitFunctionDeclaration(node, writer);
break;
case SyntaxKind.ClassDeclaration:
emitClassDeclaration(node, writer);
break;
// ... 其他节点类型
}
}
// TypeScript 源码
interface User {
name: string;
age: number;
}
function greet(user: User): string {
return `Hello, ${user.name}!`;
}
// 编译后的 JavaScript(ES5)
function greet(user) {
return "Hello, " + user.name + "!";
}
// 转换说明:
// 1. 接口声明被移除(类型擦除)
// 2. 类型注解被移除
// 3. 模板字符串转换为字符串拼接
// 4. 箭头函数转换为普通函数(如需要)
// Node 是所有 AST 节点的基类
interface Node {
kind: SyntaxKind; // 节点类型
pos: number; // 起始位置
end: number; // 结束位置
flags: NodeFlags; // 节点标志
parent: Node; // 父节点
symbol: Symbol; // 关联的符号
// 修饰符(如 public, private)
modifiers?: Modifier[];
// 装饰器
decorators?: Decorator[];
}
const enum NodeFlags {
None = 0,
ExportContext = 1 << 0,
Ambient = 1 << 1,
// ...
}
// 不同类型的 Node
interface SourceFile extends Node {
statements: Statement[];
fileName: string;
text: string;
}
interface FunctionDeclaration extends Declaration {
name: Identifier;
parameters: ParameterDeclaration[];
typeParameters?: TypeParameterDeclaration[];
returnType?: TypeNode;
body: Block;
}
interface ClassDeclaration extends Declaration {
name: Identifier;
typeParameters?: TypeParameterDeclaration[];
heritageClauses?: HeritageClause[];
members: ClassElement[];
}
// Symbol 代表命名实体
interface Symbol {
flags: SymbolFlags; // 符号标志
escapedName: __String; // 符号名称
declarations: Declaration[]; // 声明位置
valueDeclaration: Declaration; // 值声明
// 成员(类、接口等)
members?: SymbolTable;
// 导出(模块)
exports?: SymbolTable;
// 父符号
parent?: Symbol;
}
// SymbolTable 是符号的映射表
type SymbolTable = Map<__String, Symbol>;
// SymbolFlags 枚举(部分)
const enum SymbolFlags {
Function = 1 << 0,
Class = 1 << 1,
Interface = 1 << 2,
Variable = 1 << 3,
Const = 1 << 4,
Enum = 1 << 5,
Module = 1 << 6,
TypeAlias = 1 << 7,
// 组合标志
ExportValue = 1 << 10,
ExportType = 1 << 11,
Import = 1 << 12,
Alias = 1 << 13,
// 值标志
Value = Function | Class | Variable | Enum,
Type = Interface | Class | TypeAlias
}
// Type 表示类型信息
interface Type {
flags: TypeFlags; // 类型标志
symbol?: Symbol; // 关联符号
id: number; // 类型 ID
// 用于缓存和比较
checker: TypeChecker;
}
// TypeFlags 枚举(部分)
const enum TypeFlags {
Any = 1 << 0,
String = 1 << 1,
Number = 1 << 2,
Boolean = 1 << 3,
Void = 1 << 4,
Undefined = 1 << 5,
Null = 1 << 6,
Object = 1 << 7,
Union = 1 << 8,
Intersection = 1 << 9,
// ...
}
基础类型:
复合类型:
高级类型:Template Literal Types, Index Access Types, Keyof Types
// Signature 表示函数签名
interface Signature {
declaration: SignatureDeclaration;
typeParameters: TypeParameter[];
parameters: Symbol[];
// 返回类型
getReturnType(): Type;
// 类型参数实例化
instantiations?: Map<string, Signature>;
}
// 示例:函数签名
// function foo<T>(x: T): T
// 签名包含:
// - 类型参数: [T]
// - 参数: [x: T]
// - 返回类型: T
// 泛型实例化过程
function instantiateType(
type: Type,
mapper: TypeMapper
): Type {
// 1. 检查缓存
const cached = getCachedInstantiation(type, mapper);
if (cached) return cached;
// 2. 创建新类型
const instantiated = createType(type.flags);
// 3. 映射类型参数
for (const prop of type.properties) {
const mappedType = mapper(prop.type);
instantiated.properties.push({
...prop,
type: mappedType
});
}
// 4. 缓存结果
cacheInstantiation(type, mapper, instantiated);
return instantiated;
}
核心算法:基于约束的类型推导
推导步骤:
示例:const arr = [1, 2, 3] → 推导为 number[]
// 类型守卫示例
function process(value: string | number) {
if (typeof value === "string") {
// 这里 value 类型收窄为 string
return value.toUpperCase();
} else {
// 这里 value 类型收窄为 number
return value.toFixed(2);
}
}
// 类型守卫类型
type TypeGuard =
| typeof x === "string"
| x instanceof MyClass
| Array.isArray(x)
| "property" in x
| customTypeGuard(x);
// 条件类型语法
type TypeName<T> =
T extends string ? "string" :
T extends number ? "number" :
T extends boolean ? "boolean" :
T extends undefined ? "undefined" :
T extends Function ? "function" :
"object";
// 示例
type T0 = TypeName<string>; // "string"
type T1 = TypeName<number>; // "number"
type T2 = TypeName<() => void>; // "function"
// 分布式条件类型
type Boxed<T> = { value: T };
type BoxedIf<T, U> = T extends U ? Boxed<T> : T;
// 映射类型语法
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
type Optional<T> = {
[P in keyof T]?: T[P];
};
type Nullable<T> = {
[P in keyof T]: T[P] | null;
};
// 内置映射类型
interface User {
name: string;
age: number;
}
type ReadonlyUser = Readonly<User>;
// { readonly name: string; readonly age: number; }
// 访问者模式用于遍历 AST
function visitNode(node: Node, visitor: Visitor): void {
const result = visitor(node);
if (result) {
forEachChild(node, child => {
visitNode(child, visitor);
});
}
}
// 示例:收集所有标识符
function collectIdentifiers(node: Node): Identifier[] {
const identifiers: Identifier[] = [];
visitNode(node, child => {
if (isIdentifier(child)) {
identifiers.push(child);
}
return true; // 继续遍历
});
return identifiers;
}
// 工厂模式用于创建 AST 节点
const factory = {
createSourceFile(
statements: Statement[],
flags: NodeFlags
): SourceFile {
return {
kind: SyntaxKind.SourceFile,
statements,
flags,
// ... 其他属性
};
},
createFunctionDeclaration(
name: Identifier,
parameters: ParameterDeclaration[],
body: Block
): FunctionDeclaration {
return {
kind: SyntaxKind.FunctionDeclaration,
name,
parameters,
body,
// ... 其他属性
};
}
};
缓存层级:
// 缓存实现
interface CacheSystem {
nodeCache: Map<NodeId, NodeInfo>;
symbolCache: Map<SymbolId, SymbolInfo>;
typeCache: Map<TypeId, TypeInfo>;
instantiationCache: Map<string, Type>;
}
增量编译策略:
// 增量编译 API
interface IncrementalCompiler {
compile(file: SourceFile): Program;
invalidate(file: string): void;
getAffectedFiles(): string[];
}
懒加载策略:
性能提升:大型项目编译速度提升 30-50%
内存优化:
内存分析:
// 错误恢复策略
function parseStatement(): Statement {
try {
switch (token()) {
case SyntaxKind.FunctionKeyword:
return parseFunctionDeclaration();
case SyntaxKind.ClassKeyword:
return parseClassDeclaration();
default:
// 错误恢复:跳过当前 token
error(Diagnostics.Statement_expected);
return createMissingNode();
}
} catch (e) {
// 严重错误:返回错误节点
return createErrorNode();
}
}
// 诊断信息结构
interface Diagnostic {
file: SourceFile;
start: number;
length: number;
messageText: string | DiagnosticMessageChain;
category: DiagnosticCategory;
code: number;
relatedInformation?: DiagnosticRelatedInformation[];
}
// 诊断类别
const enum DiagnosticCategory {
Warning = 0, // 警告
Error = 1, // 错误
Suggestion = 2, // 建议
Message = 3 // 消息
}
// 示例:Type 'string' is not assignable to type 'number' (2322)
语言服务 API:
源码位置:src/services/ 目录
// TypeScript 插件接口
interface Plugin {
// 插件名称
name: string;
// 插件版本
version: string;
// 插件初始化
init(context: PluginContext): void;
// 自定义转换
transform?(node: Node): Node;
// 自定义诊断
getDiagnostics?(file: SourceFile): Diagnostic[];
}
测试类型:
测试工具:
测试覆盖率:80%+ 代码覆盖率
// tsconfig.json 推荐配置
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"lib": ["ES2020"],
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"moduleResolution": "node",
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
}
}
编译优化:
编码实践:
性能提升:正确配置可提升 50%+ 编译速度
TypeScript 7.0 计划:
预计发布:2026-2027 年
核心收获:
下一步:深入阅读 TypeScript 源码,实践编译器开发