如何使用TypeScript Compile API检测Math、console等内置对象
基于TypeScript Compiler API识别JS内置对象的实现方案
实现思路
TypeScript Compiler API(下称TS API)内置了所有JS标准内置对象的类型声明信息,无需硬编码匹配标识符名称即可实现高准确率的检测,核心思路分为3步:
- 遍历目标源码的抽象语法树(AST),提取所有标识符(
Identifier)节点 - 调用TS API的类型检查器(
TypeChecker)获取每个标识符对应的符号(Symbol)信息 - 校验符号的声明来源是否为TS官方内置的类型声明文件,同时匹配目标内置对象的名称即可
该方案的优势是可以自动排除用户自定义的同名全局变量,不会出现误判
具体操作方法
前置依赖安装
执行命令安装所需依赖:npm install typescript @types/typescript
核心实现步骤
- 初始化TS编译实例
Program是TS编译流程的入口,需要传入目标文件路径和编译配置,同时获取核心的类型检查器实例:
import * as ts from 'typescript'; // 对应tsconfig.json的编译配置 const compilerOptions: ts.CompilerOptions = { target: ts.ScriptTarget.ESNext, // 配置需要包含的类型库,确保覆盖你要检测的内置对象对应的声明 lib: ['ESNext', 'DOM'], }; // 创建Program实例,第一个参数为你要检测的目标文件路径列表 const program = ts.createProgram(['./src/index.ts'], compilerOptions); // 获取类型检查器,用于获取节点的类型、符号信息 const typeChecker = program.getTypeChecker();
- 遍历AST并检测内置对象
通过AST访问器遍历所有节点,对标识符节点做内置对象判断:
// 定义要检测的内置对象列表 const targetBuiltIns = new Set(['Math', 'console', 'Promise', 'window']); function traverseNode(node: ts.Node) { // 仅处理标识符类型的节点 if (ts.isIdentifier(node)) { // 获取标识符对应的符号信息 const symbol = typeChecker.getSymbolAtLocation(node); if (!symbol) return; // 校验符号是否为全局内置对象:所有声明均来自TS官方的内置类型声明文件 const isBuiltIn = symbol.declarations?.every(declaration => { const declSource = declaration.getSourceFile(); // TS官方内置类型文件均以lib.为前缀,以.d.ts为后缀 return declSource.fileName.match(/lib\..*\.d\.ts$/) !== null; }) ?? false; // 匹配到目标内置对象时输出信息 if (isBuiltIn && targetBuiltIns.has(node.text)) { const pos = ts.getLineAndCharacterOfPosition(node.getSourceFile(), node.getStart()); console.log(`检测到内置对象${node.text},位置:第${pos.line + 1}行第${pos.character + 1}列`); } } // 递归遍历子节点 ts.forEachChild(node, traverseNode); } // 遍历所有目标源文件,跳过node_modules和内置声明文件 program.getSourceFiles().forEach(sourceFile => { if (!sourceFile.fileName.includes('node_modules') && !sourceFile.fileName.match(/lib\..*\.d\.ts$/)) { traverseNode(sourceFile); } });
注意事项
- 如果需要检测非标准的全局对象(比如浏览器环境的
chrome、Node.js环境的process),可以对应调整compilerOptions.lib配置,同时修改声明来源的校验规则即可 - 如果项目中存在通过
declare global自定义的全局变量,该方案会自动排除,不会识别为内置对象 - 若目标代码未配置TS类型声明,不存在对应符号的标识符会被自动跳过,不会出现误判
内容的提问来源于stack exchange,提问作者Rob H
相关产品推荐
相关产品推荐

