Custom Transformers and Code Generation
Write compiler transforms that modify the AST.
Custom Transformers and Code Generation is a free TypeScript Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the TypeScript Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
What Are Transformers?
TypeScript transformers are functions that receive an AST node and return a (possibly modified) node. They run during compilation to generate custom output.
import ts from "typescript";
type Transformer = ts.TransformerFactory<ts.SourceFile>;Transformer Factory Shape
A transformer factory takes a TransformationContext and returns a function that transforms SourceFile nodes.
const myTransformer: ts.TransformerFactory<ts.SourceFile> =
(ctx) => (sf) => {
function visit(node: ts.Node): ts.Node {
// Modify node here
return ts.visitEachChild(node, visit, ctx);
}
return ts.visitNode(sf, visit) as ts.SourceFile;
};Visiting with Context
ts.visitEachChild (not forEachChild) is used inside transformers because it reconstructs modified nodes properly.
function visit(node: ts.Node): ts.Node {
if (ts.isStringLiteral(node)) {
return ts.factory.createStringLiteral(node.text.toUpperCase());
}
return ts.visitEachChild(node, visit, ctx);
}Creating New Nodes with ts.factory
The ts.factory object provides methods to create every kind of AST node.
const newCall = ts.factory.createCallExpression(
ts.factory.createIdentifier("console.log"),
undefined,
[ts.factory.createStringLiteral("hello")]
);Applying Transformers to a Program
Pass transformers to the customTransformers option of program.emit.
program.emit(undefined, undefined, undefined, false, {
before: [myTransformer],
});Code Generation: Printing Nodes
Use ts.createPrinter to convert AST nodes back to source code strings without running the full compiler.
const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
const result = printer.printNode(
ts.EmitHint.Unspecified,
newCall,
sf
);
console.log(result); // console.log("hello")Generating Entire Source Files
You can create a complete source file from scratch using ts.factory.createSourceFile or by assembling a list of statement nodes.
const statements = [
ts.factory.createExpressionStatement(
ts.factory.createCallExpression(
ts.factory.createIdentifier("console.log"),
undefined,
[ts.factory.createStringLiteral("generated!")]
)
),
];Transforming Imports
A common use case is transforming import paths — for example, rewriting aliased paths to relative paths at emit time.
if (ts.isImportDeclaration(node)) {
const spec = node.moduleSpecifier as ts.StringLiteral;
if (spec.text.startsWith("@app/")) {
return ts.factory.updateImportDeclaration(
node, node.modifiers, node.importClause,
ts.factory.createStringLiteral(spec.text.replace("@app/", "../")),
node.assertClause
);
}
}Testing Transformers
Test transformers by applying them to a small source file and asserting the printed output matches the expected string.
const result = ts.transpileModule("const x = 'hello';", {
compilerOptions: { target: ts.ScriptTarget.ES2020 },
transformers: { before: [myTransformer] },
});
console.log(result.outputText);Plugin Systems
Some build tools (like ttypescript / ts-patch) let you register transformers as plugins in tsconfig, making them transparent to the dev workflow.
// tsconfig.json with ts-patch:
// "plugins": [{ "transform": "./my-transformer.js" }]Recap: Custom Transformers
Transformers let you rewrite TypeScript code at the AST level during compilation. Use ts.visitEachChild for recursive traversal, ts.factory to create nodes, and ts.createPrinter to generate source text.
Quick Check
Which object do you use to create new AST nodes in a transformer?
What You Learned
Custom transformers modify the TypeScript AST at compile time. Use ts.visitEachChild to recurse, ts.factory to build new nodes, and program.emit with customTransformers to apply them.
Frequently asked questions
Is the “Custom Transformers and Code Generation” lesson free?
Yes — the full text of “Custom Transformers and Code Generation” is free to read here on the web, and the TypeScript Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the TypeScript Academy course, upgrade to CoddyKit PRO.
What will I learn in “Custom Transformers and Code Generation”?
Write compiler transforms that modify the AST. You practise TypeScript Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start TypeScript Academy?
No prior experience is required. TypeScript Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Custom Transformers and Code Generation” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this TypeScript Academy lesson?
Yes. Every TypeScript Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Creating a TypeScript Program with the API
- Traversing the AST with Visitors
- Custom Transformers and Code Generation
- Building a Simple Linting Tool