TypeScript类型检查与语法树分析探索

前言:最近在做关于ide中对于typescript相关的类型检查,扒开ts源码拜读了一番,这里做个总结,也算是纪念我们那逝去的秀发。

TypeScript的DNA鉴定中心:源码级解剖现场

(想象这里有个编译器正在给代码做开胸手术)

让我们穿上白大褂,戴上编译器专家的胸牌,直接进入 TypeScript 的源码解剖室。今天,我们要在显微镜下解析 TypeScript 编译器的运行过程,探究它如何分析、检查和变形你的代码。


一、语法解析:源代码的"基因测序"

现场直击 :当你的代码被扔进 tsc(TypeScript 编译器),它的第一步是对代码进行 词法分析语法解析 ,这就像 CSI 鉴证科在对DNA样本进行测序,拆解基因片段,并拼装成完整的基因组。

typescript 复制代码
// 来自 TypeScript 源码的简化版解析逻辑

function parseSourceFile(): SourceFile {

    const result = createSourceFile();

    while (true) {

        const token = scanner.scan(); // 词法分析:拆解DNA片段

        switch (token) {

            case SyntaxKind.LetKeyword:

                parseVariableStatement(result);

                break;

            case SyntaxKind.InterfaceKeyword:

                parseInterfaceDeclaration(result);

                break;

            // ...处理其他语法结构

        }

    }

    return result;

}

解析过程拆解

  1. 词法分析(Lexical Analysis) :扫描代码,把 const cyberpunk = 2077; 变成 Token 序列 [const] [cyberpunk] [=] [2077] [;],就像 DNA 片段被拆解成碱基对。

  2. 语法分析(Syntax Analysis) :将这些 Token 组装成 AST(抽象语法树),就像基因拼接成完整染色体。

  3. AST 结构:每个 ; 号都像 DNA 终止子,标志着一个语法片段的结束。

AST 实况转播

使用 TypeScript 编译器 API 观察代码的"基因图谱":

typescript 复制代码
import ts from 'typescript';

  


const code = `const 赛博朋克 = 2077`;

const ast = ts.createSourceFile('demo.ts', code, ts.ScriptTarget.Latest);

  


console.log(ast.statements[0]);  *// 输出变量声明的基因序列*

它会生成如下 AST 结构:

typescript 复制代码
VariableStatement {

    declarationList: VariableDeclarationList {

        declarations: [

            VariableDeclaration {

                name: Identifier { text: "赛博朋克" },  *// 变量名基因片段*

                initializer: NumericLiteral { text: "2077" }  *// 数值型DNA*

            }

        ]

    }

}

TypeScript 解析器的工作就像 DNA 测序仪,把代码拆解成最基本的基因单位,并构建完整的生物体------也就是 AST!

二、类型检查:编译器的"法医鉴定"

在 TypeScript 编译器的 checker.ts 文件里,有一支法医团队,他们负责检查代码的 DNA 是否匹配。

typescript 复制代码
*// 类型检查核心代码(简化版)*

function checkPropertyAccess(node: PropertyAccessExpression) {

    const type = checkExpression(node.expression);  *// 先检查对象的类型*

    const propName = node.name.text;  *// 获取属性名*

    if (!type.getProperty(propName)) {  *// 开始比对 DNA*

        error(

            node.name,

            `类型'${typeToString(type)}'上不存在属性'${propName}'`

        );  *// 发现 DNA 不匹配,抛出错误报告*

    }

}

血腥案例

const 死因 = "他杀";

console.log(死因.toFixed(2)); // 凶器:字符串的 toFixed 方法

编译器的调查报告:

  1. 鉴定 死因 的类型是 string

  2. 查阅 string 的 DNA 记录,发现它没有 toFixed 方法

  3. 立即拉响警报:"非法调用,DNA 不匹配!"

类型推断的 X 光片

typescript 复制代码
*// 类型推断机制*

function inferTypeFromExpression(node: Expression) {

    if (node.kind === SyntaxKind.NumericLiteral) {

        return numberType;  *// 数字字面量 -> number*

    }

    if (node.kind === SyntaxKind.StringLiteral) {

        return stringType;  *// 字符串字面量 -> string*

    }

    *// ...其他推断逻辑*

}

这样,每个变量的类型都被精准地标记在 DNA 序列上。

三、AST 操纵:代码整容手术

有时候,我们需要修改代码结构,比如自动添加类型注解,这就像给代码做整容手术。

typescript 复制代码
import ts from 'typescript';


*// 原始代码*

const ast = ts.createSourceFile('demo.ts', 'let 年龄 = "二十五";', ts.ScriptTarget.Latest);


const varStatement = ast.statements[0] as ts.VariableStatement;

const varDecl = varStatement.declarationList.declarations[0];


*// 给变量添加类型注解*

varDecl.type = ts.factory.createTypeReferenceNode("number");

  
*// 打印修改后的代码*

const printer = ts.createPrinter();

console.log(printer.printFile(ast));

 
**效果**:

  
let 年龄: number = "二十五";  *// 这显然是不对的!*

编译器当场发飙:

类型"string"的值不能赋给类型"number"的变量

就像给熊猫染色,编译器这个"动物保护组织"立刻抗议。

四、类型体操的解剖实验室

泛型类型推导是 TypeScript 里最精密的 DNA 重组技术。例如:

type 量子纠缠 = T extends { 态: infer U } ? U : never;

当我们传入:

type 薛定谔的猫 = 量子纠缠<{ 态: "既死又活" }>;

TypeScript 内部的 DNA 鉴定过程:

  1. 发现 T 里包含 { 态: "既死又活" }

  2. 提取 态 的 DNA 片段,得到 "既死又活"

  3. 最终推导出 type 薛定谔的猫 = "既死又活"

五、编译器的"黑匣子"解密

调试秘籍

运行 tsc --showConfig,你会看到编译器的手术方案:

typescript 复制代码
{

    "compilerOptions": {

        "strict": true,  *// 开启严格模式*

        "noImplicitAny": true,  *// 禁止隐式 any*

        "target": "ES2022"  *// 目标环境设定*

    }

}

如果想加速编译,可以启用:

typescript 复制代码
{

    "incremental": true  *// 增量编译,加快二次编译速度*

}

后记

下次你的 IDE 报错时,不妨想象 TypeScript 编译器里有个穿白大褂的怪博士,拿着 DNA 采样器,对着你的代码说:

"年轻人,你这个变量整容过吧?身份证和脸对不上啊!"

相关推荐
菜鸟码猿1 天前
TS内置工具类型
前端·typescript
鸿蒙开发工程师—阿辉1 天前
HarmonyOS Next元服务网络请求封装实践
网络·华为·typescript·harmonyos·元服务
MurphyChen2 天前
TypeScript 官方宣布弃用 Enum?Enum 何罪之有?
前端·javascript·typescript
Homilier2 天前
开发vue小游戏:数字华龙道
前端·vue.js·typescript·数字华龙道
慢知行2 天前
TypeScript 封装 Date 格式化函数:简洁又高效
前端·javascript·typescript
Hamm3 天前
前端不在TypeScript使用类,如何写出清晰优雅的代码?
前端·vue.js·typescript
shmily_yy3 天前
TS为什么被叫做类型体操
typescript
AI陪跑3 天前
从“静态尴尬”到“真实交互”:GrapesJS Drawer 组件的创新性设计
前端·人工智能·typescript
GH小杨3 天前
鸿蒙全栈开发 D1
华为·typescript·harmonyos