如何将赋值 属性 添加到打字稿编译器 api 中的现有对象文字表达式?
How to add assignment property to existing object literal expression in typescript compiler api?
我想使用打字稿 AST 添加 bar: true
到 x
对象。
此代码生成 bar: true
:
factory.createPropertyAssignment(
factory.createIdentifier("bar"),
factory.createTrue()
);
我知道我需要 return 这个函数才能将它添加到 AST。如果我这样做那么问题是代码将覆盖 foo: true
.
有什么想法可以添加 bar: true
而不会丢失 foo: true
吗?
代码:
import * as ts from "typescript";
const code = `
const x = {
foo: true
})
`;
const node = ts.createSourceFile("x.ts", code, ts.ScriptTarget.Latest);
const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
export const add = (context) => (rootNode) => {
function visit(node) {
const { factory } = context;
// if (node.kind === ts.SyntaxKind.ObjectLiteralExpression) {
// return factory.createPropertyAssignment(
// factory.createIdentifier("bar"),
// factory.createTrue()
// );
// }
return ts.visitEachChild(node, visit, context);
}
return ts.visitNode(rootNode, visit);
};
const result = ts.transform(node, [add]);
// console.log({ result });
const transformedSourceFile = result.transformed[0];
const out = printer.printFile(transformedSourceFile);
console.log({ out });
您正在为 ObjectLiteralExpression 节点的访问者返回 PropertyAssignment 节点,该节点替换了完整的对象文字。
相反,您可以更新此节点的属性成员以包含新的 属性:
export const add = (context) => (rootNode) => {
function visit(node) {
const { factory } = context;
if (node.kind === ts.SyntaxKind.ObjectLiteralExpression) {
// Update node.properties ------>
node.properties.push(
factory.createPropertyAssignment(
factory.createIdentifier("bar"),
factory.createTrue()
)
);
return node;
}
return ts.visitEachChild(node, visit, context);
}
return ts.visitNode(rootNode, visit);
};
如果您在打字稿中执行此操作,node.properties
是只读的。类型安全的方法是当你想改变当前节点时使用 factory.update*()
方法并且 return 它:
export const add: ts.TransformerFactory<ts.SourceFile> = (context) => (rootNode) => {
function visit(node: ts.Node): ts.VisitResult<ts.Node> {
const { factory } = context;
// using the provided typeguard to narrow the node kind
if (ts.isObjectLiteralExpression(node)) {
return factory.updateObjectLiteralExpression(node, [
// include the existing properties
...node.properties,
// add your generated property
factory.createPropertyAssignment(
factory.createIdentifier("bar"),
factory.createTrue()
)
]
);
}
return ts.visitEachChild(node, visit, context);
}
return ts.visitNode(rootNode, visit);
};
我想使用打字稿 AST 添加 bar: true
到 x
对象。
此代码生成 bar: true
:
factory.createPropertyAssignment(
factory.createIdentifier("bar"),
factory.createTrue()
);
我知道我需要 return 这个函数才能将它添加到 AST。如果我这样做那么问题是代码将覆盖 foo: true
.
有什么想法可以添加 bar: true
而不会丢失 foo: true
吗?
代码:
import * as ts from "typescript";
const code = `
const x = {
foo: true
})
`;
const node = ts.createSourceFile("x.ts", code, ts.ScriptTarget.Latest);
const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
export const add = (context) => (rootNode) => {
function visit(node) {
const { factory } = context;
// if (node.kind === ts.SyntaxKind.ObjectLiteralExpression) {
// return factory.createPropertyAssignment(
// factory.createIdentifier("bar"),
// factory.createTrue()
// );
// }
return ts.visitEachChild(node, visit, context);
}
return ts.visitNode(rootNode, visit);
};
const result = ts.transform(node, [add]);
// console.log({ result });
const transformedSourceFile = result.transformed[0];
const out = printer.printFile(transformedSourceFile);
console.log({ out });
您正在为 ObjectLiteralExpression 节点的访问者返回 PropertyAssignment 节点,该节点替换了完整的对象文字。
相反,您可以更新此节点的属性成员以包含新的 属性:
export const add = (context) => (rootNode) => {
function visit(node) {
const { factory } = context;
if (node.kind === ts.SyntaxKind.ObjectLiteralExpression) {
// Update node.properties ------>
node.properties.push(
factory.createPropertyAssignment(
factory.createIdentifier("bar"),
factory.createTrue()
)
);
return node;
}
return ts.visitEachChild(node, visit, context);
}
return ts.visitNode(rootNode, visit);
};
如果您在打字稿中执行此操作,node.properties
是只读的。类型安全的方法是当你想改变当前节点时使用 factory.update*()
方法并且 return 它:
export const add: ts.TransformerFactory<ts.SourceFile> = (context) => (rootNode) => {
function visit(node: ts.Node): ts.VisitResult<ts.Node> {
const { factory } = context;
// using the provided typeguard to narrow the node kind
if (ts.isObjectLiteralExpression(node)) {
return factory.updateObjectLiteralExpression(node, [
// include the existing properties
...node.properties,
// add your generated property
factory.createPropertyAssignment(
factory.createIdentifier("bar"),
factory.createTrue()
)
]
);
}
return ts.visitEachChild(node, visit, context);
}
return ts.visitNode(rootNode, visit);
};