TS 编译器 API:阻止导出。出现在没有导出修饰符的节点上

TS compiler API: prevent Export. to appear on nodes where there is not a export modifier

在 js 中,导出的变量声明如下: "Exports.my_var = cool_value ",

当使用 Typyscript 编译器时 api 我有一些最初具有导出修饰符的变量,例如:

export let a = 1;
a = a + 1;

解决于

Exports.a = 1;
Exports.a = Exports.a + 1;

但我不想将它们导出到 js 文件中,我尝试删除节点上的导出修饰符,但它们仍然与导出一起编译。

[更新]

一些示例代码

变形金刚:

 ast = VisitNode(ast,function() {
                let visitor = (n) => {
                    console.log('VISITING',n.kind);
                    if(n.modifiers) {
                        n.modifiers = undefined;
                        console.log(n.modifiers);
                    }

                    return visitEachChild(n,visitor,ctx);
                }

                return visitor;
            }());

 return ast;

VisitNodevisitEachChild 是自定义函数,但作为 ts 工作。一个。

test.ts:

export let a = 30;
export let z = 10;

z = z + a;
a = a + z;
export let c = 'hello';
c = 'hey there';

输出:

exports.a = 30;
exports.z = 10;
exports.z = exports.z + exports.a;
exports.a = exports.a + exports.z;
exports.c = 'hello';
exports.c = 'hey there';

似乎一种方法是将所有标识符设置为具有 LocalName 发出标志并删除源文件中的内部 externalModuleIndicator 属性。

const transformer = <T extends ts.Node>(context: ts.TransformationContext) =>
    (rootNode: T) => {
        function visit(sourceFile: ts.Node): ts.Node {
            if (!ts.isSourceFile(sourceFile))
                throw new Error("This code only works with a source file.");

            // strip this internal property to get rid of `exports.__esModule = true;`
            delete (sourceFile as any).externalModuleIndicator;

            return ts.visitEachChild(sourceFile, statement => {
                // remove the export modifiers
                if (statement.modifiers) {
                    const newModifiers = statement.modifiers
                        .filter(m => m.kind !== ts.SyntaxKind.ExportKeyword);
                    statement.modifiers = ts.createNodeArray(newModifiers);
                }

                return ts.visitEachChild(statement, visitIdentifiers, context);

                function visitIdentifiers(descendant: ts.Node) {
                    if (ts.isIdentifier(descendant))
                        return ts.setEmitFlags(descendant, ts.EmitFlags.LocalName);
                    return ts.visitEachChild(descendant, visitIdentifiers, context);
                }
            }, context);
        }
        return ts.visitNode(rootNode, visit);
    };

基本上,编译器会在转换阶段之前收集所有要导出的名称,然后用 exports. 前缀替换所有与导出名称匹配的标识符。所以剥离 export 修饰符没有效果,因为编译器已经决定了要导出的名称。