TypeScript
Custom transformer
Learn to write your own transformer.
Writing a custom transformer
When writing your own transformer you define a visitor function. The visitor recognizes specific nodes and replaces them with new nodes built via ts.factory. For other nodes you descend with ts.visitEachChild.
function visit(node: ts.Node): ts.Node {
if (ts.isStringLiteral(node)) {
return ts.factory.createStringLiteral("X");
}
return ts.visitEachChild(node, visit, context);
}
When the visitor returns a new node, that branch is replaced entirely.
Node replacement and visitEachChild
There are two ways to change a node: return a completely new node, or update the existing node's fields with ts.factory.updateX. visitEachChild automatically updates the parent when a child changes.
// visitEachChild is recommended even for identity
return ts.visitEachChild(node, visit, context);
Exercise Replace strings with "X"
Create a source with const a = 'merhaba'; and const b = 'dünya';. Write a transformer that replaces every StringLiteral node found with ts.isStringLiteral by ts.factory.createStringLiteral("X"). Apply it with ts.transform and print the result with the Printer.
Show example solution
import ts from "typescript";
const sourceText = `const a = 'merhaba';\nconst b = 'dünya';`;
const sf = ts.createSourceFile("app.ts", sourceText, ts.ScriptTarget.Latest, true);
const transformer: ts.TransformerFactory<ts.SourceFile> = (context) => {
function visit(node: ts.Node): ts.Node {
if (ts.isStringLiteral(node)) {
return ts.factory.createStringLiteral("X");
}
return ts.visitEachChild(node, visit, context);
}
return (node) => ts.visitEachChild(node, visit, context);
};
const result = ts.transform(sf, [transformer]);
const printer = ts.createPrinter();
process.stdout.write(printer.printFile(result.transformed[0] as ts.SourceFile));
result.dispose();
Test yourself
-
To change a node in a custom transformer, what do you do?
- You call program.getTypeChecker
- You mutate the node's text property directly
- You return a new node in the visitor function
- You print the node with console.log
Show answer
You return a new node in the visitor function — AST nodes are immutable; you cannot mutate the text property. When the visitor returns a new node, that branch is replaced.
-
Replace a string literal
function visit(node: ts.Node): ts.Node {
if (ts.isStringLiteral(node)) {
return ts.factory.____("X");
}
return ts.visitEachChild(node, visit, context);
}
Show answer
function visit(node: ts.Node): ts.Node {
if (ts.isStringLiteral(node)) {
return ts.factory.createStringLiteral("X");
}
return ts.visitEachChild(node, visit, context);
}
-
Custom transformer parts
- Visitor fonksiyonu
- Recognizes and returns nodes
- ts.factory.createStringLiteral
- Produces a new string node
- ts.visitEachChild
- Transforms child nodes
- ts.isStringLiteral
- Tests the node kind
Next lesson: Summary - Transformer