如果你只是想修改源文件文本添加属性,那么可以这样:
- 从 AST 中获取对象文字表达式(使用 https://ts-ast-viewer.com 有助于了解 AST 的外观)。
- 使用
ts.updateObjectLiteral 为具有新属性的旧节点获取新节点。
- 打印出新节点的文本,并用打印的节点文本修改原始文本。
- 如有必要,重新解析为新的 AST,或仅使用修改后的文本。
请注意,打印对象文字将删除您之前拥有的任何自定义格式,因为打印机以自己的方式打印节点。之后您可能希望通过 prettier 或其他格式化程序运行代码。
例子:
import * as ts from "typescript";
// parse the AST
const sourceFile = ts.createSourceFile("file.ts", "const a = { foo: 'bar' };",
ts.ScriptTarget.Latest, false);
// get the object literal expression
const objectLiteralExpression = sourceFile.statements.find(ts.isVariableStatement)!
.declarationList.declarations[0].initializer as ts.ObjectLiteralExpression;
// get a transformed node with the new property and print it
const transformedOle = ts.updateObjectLiteral(objectLiteralExpression, [
...objectLiteralExpression.properties,
ts.createPropertyAssignment("can", ts.createStringLiteral("haz"))
]);
const newNodeText = ts.createPrinter()
.printNode(ts.EmitHint.Unspecified, transformedOle, sourceFile);
// get the new source file text and reparse it to a new AST
const oldText = sourceFile.text;
const newText = oldText.substring(0, objectLiteralExpression.getStart(sourceFile, true))
+ newNodeText + oldText.substring(objectLiteralExpression.end);
const newSourceFile = ts.createSourceFile("file.ts", newText, ts.ScriptTarget.Latest, false);
// outputs: `const a = { foo: "bar", can: "haz" };`
console.log(newText);
如果您想在发射时执行此操作,请考虑为Program#emit(...) 提供自定义转换器。