TypeScript转换器中如何快速将Expression转为对应的JavaScript对象?
TypeScript 转换器获取调用参数实际值方案
TypeScript 编译器 API 没有内置的通用方法可以直接从 Expression 实例导出对应的 JavaScript 对象,需要根据表达式的类型手动做解析处理,具体实现思路如下:
场景1:参数为 ObjectLiteralExpression (直接传入对象字面量)
这种场景处理最简单,直接遍历对象字面量的属性节点提取键值即可,示例代码:
function parseObjectLiteral(expr: ts.ObjectLiteralExpression): Record<string, any> { const result = {}; for (const prop of expr.properties) { // 仅处理普通的属性赋值节点 if (ts.isPropertyAssignment(prop)) { const key = prop.name.getText(); const valueNode = prop.initializer; // 这里仅处理字符串字面量,需要其他类型可自行扩展分支 if (ts.isStringLiteral(valueNode)) { result[key] = valueNode.text; } } } return result; }
场景2:参数为 Identifier (传入变量引用)
这种场景需要借助 TypeScript 的类型检查器(TypeChecker)实例,先定位到变量的声明节点,再提取声明的初始值解析:
function parseIdentifier(expr: ts.Identifier, checker: ts.TypeChecker): Record<string, any> | null { // 获取标识符对应的符号 const symbol = checker.getSymbolAtLocation(expr); if (!symbol?.declarations?.length) return null; // 取第一个声明节点 const decl = symbol.declarations[0]; // 仅处理const变量声明的情况 if (ts.isVariableDeclaration(decl) && decl.initializer && ts.isObjectLiteralExpression(decl.initializer)) { return parseObjectLiteral(decl.initializer); } return null; }
完整的 convert 函数实现
function convert(callExpression: ts.CallExpression, checker: ts.TypeChecker): Record<string, string> | null { const argumentExpression = callExpression.arguments[0]; if (!argumentExpression) return null; if (ts.isObjectLiteralExpression(argumentExpression)) { return parseObjectLiteral(argumentExpression); } else if (ts.isIdentifier(argumentExpression)) { return parseIdentifier(argumentExpression, checker); } return null; }
注意事项
- 上述实现仅处理静态常量值场景,如果变量的赋值依赖运行时逻辑、动态计算、函数返回值,编译阶段无法获取到实际值
- 如果需要支持数组、数字、布尔、嵌套对象等其他类型的取值,可自行扩展对应类型的判断分支
- 生产环境使用建议补充异常处理逻辑,避免非法节点导致转换器崩溃
内容的提问来源于stack exchange,提问作者distante
相关产品推荐
相关产品推荐

