如何通过编程方式获取TypeScript中指定声明的类型?
TypeScript 批量提取全局挂载类型生成接口方案
要实现批量分析代码中makeGlobal调用、自动生成Window扩展接口的需求,直接调用TypeScript官方Compiler API即可,底层逻辑和IDE计算hover类型的逻辑完全一致,不会出现类型偏差。
实现步骤
- 安装官方依赖
npm install typescript -D
- 编写解析脚本核心逻辑
import * as ts from 'typescript'; import * as fs from 'fs'; import * as path from 'path'; // 读取项目tsconfig配置 const tsconfigPath = path.resolve(__dirname, './tsconfig.json'); const configFile = ts.readConfigFile(tsconfigPath, ts.sys.readFile); const parsedConfig = ts.parseJsonConfigFileContent(configFile.config, ts.sys, path.dirname(tsconfigPath)); // 创建TS程序实例,和IDE用的类型计算实例逻辑一致 const program = ts.createProgram(parsedConfig.fileNames, parsedConfig.options); const checker = program.getTypeChecker(); // 存储收集到的全局键值类型 const globalEntries: Record<string, string> = {}; // 遍历所有待分析的源文件 for (const sourceFile of program.getSourceFiles()) { // 跳过node_modules和.d.ts声明文件,按需调整过滤规则 if (sourceFile.isDeclarationFile || sourceFile.fileName.includes('node_modules')) continue; // 遍历AST节点查找makeGlobal调用 ts.forEachChild(sourceFile, function walk(node: ts.Node) { if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === 'makeGlobal') { // 第一个参数是全局挂载的key,第二个是挂载的值 const keyNode = node.arguments[0]; const valueNode = node.arguments[1]; if (!ts.isStringLiteral(keyNode) || !valueNode) return; const key = keyNode.text; // 核心:获取值节点的完整类型,和IDE hover结果完全一致 const valueType = checker.getTypeAtLocation(valueNode); // 把类型转成可拼接的字符串 const typeString = checker.typeToString(valueType); globalEntries[key] = typeString; } ts.forEachChild(node, walk); }); } // 生成最终的.d.ts声明文件内容 const declarationContent = `interface Window { ${Object.entries(globalEntries).map(([key, type]) => ` ${key}: ${type}`).join('\n')} }`; fs.writeFileSync(path.resolve(__dirname, './global.d.ts'), declarationContent);
- 运行脚本即可在项目根目录生成符合需求的
global.d.ts声明文件,对应你给出的示例代码,生成结果和你要求的输出完全一致。
注意事项
必须使用项目实际生效的tsconfig配置初始化TS程序,否则会因为编译选项、类型包含范围的差异,导致生成的类型和IDE展示的结果不一致。
内容的提问来源于stack exchange,提问作者Alex Kozack
相关产品推荐
相关产品推荐

