Search code examples
typescripttypescript-compiler-api

TypeScript Compiler API: how to create a transformer that's replace a node when emit files


I'm tryng to write a Typescript Transformer using TypeScript Compiler API that's appends a suffix to every node identifier, so far what I have is the following code:

main.ts

import * as ts from "typescript";

const transformerFactory: ts.TransformerFactory<ts.Node> = context => rootNode => {
    function visit(node: ts.Node): ts.Node {
        node = ts.visitEachChild(node, visit, context);
        if (ts.isIdentifier(node))
            return context.factory.createIdentifier(node.text + "suffix");
            
        return node;
    }
    return ts.visitNode(rootNode, visit);
};

const program = ts.createProgram(["source.ts"], {})

// PRINTER
const sourceFile = program.getSourceFile("source.ts")
const transformationResult = ts.transform(sourceFile, [transformerFactory])
const transformedSourceFile = transformationResult.transformed[0];
const printer = ts.createPrinter();
const result = printer.printNode(
    ts.EmitHint.Unspecified, 
    transformedSourceFile, 
    undefined
);
console.log(result)

// EMIT
program.emit();

As input file I wrote a file called source.ts with the following content:

source.ts

const test_____: number = 1 + 2;

It's works well printing to console, but does nothing whem file is emited, see below the results:

console.log

const test_____suffix: number = 1 + 2;

source.js

const test_____ = 1 + 2;

How can I make the emited file to have the same as the one printed on the console?


Solution

  • The transforming and printing that's being done in that code is outside the emit process. Instead of using the transform and printer APIs, you need to provide the transformer factory to the emit method:

    const program = ts.createProgram(["source.ts"], {});
    
    program.emit(undefined, undefined, undefined, undefined, {
      before: [transformerFactory]
    });