AST traversal
- TypeScript course
- Expert
- Lesson 3/35
- 4 min
Learn AST traversal with forEachChild.
What is forEachChild?
ts.forEachChild(node, visitFn) visits every direct child of an AST node in order and calls visitFn for each. Combined with a recursive visit function it is the standard way to walk the whole tree.
import ts from "typescript";
const sf = ts.createSourceFile(
"app.ts", "const a = 1;", ts.ScriptTarget.Latest, true
);
function visit(node: ts.Node) {
console.log(ts.SyntaxKind[node.kind]);
ts.forEachChild(node, visit);
}
visit(sf);SyntaxKind and type guards
Every node has a numeric .kind; ts.SyntaxKind[kind] gives its name. To test for specific node kinds you use type guards such as ts.isIdentifier, ts.isFunctionDeclaration and ts.isVariableStatement.
function visit(node: ts.Node) {
if (ts.isIdentifier(node)) {
console.log(node.text);
}
ts.forEachChild(node, visit);
}Practice Count identifiers
Create a source file from function topla(a: number, b: number): number { return a + b; } with ts.createSourceFile. Write a recursive visit function; count Identifier nodes with ts.isIdentifier and descend with ts.forEachChild. Print the total count.
Starter code
import * as ts from "typescript";
// Kaynak: function topla(a: number, b: number): number { return a + b; }
// SourceFile oluştur
// visit fonksiyonu yaz: Identifier düğümleri say
// forEachChild ile alt düğümlere in
// Toplam sayıyı yazdır
// kodunu buraya yazSample solution
import ts from "typescript";
const sourceText = "function topla(a: number, b: number): number { return a + b; }";
const sf = ts.createSourceFile("app.ts", sourceText, ts.ScriptTarget.Latest, true);
let count = 0;
function visit(node: ts.Node) {
if (ts.isIdentifier(node)) {
count++;
}
ts.forEachChild(node, visit);
}
visit(sf);
console.log(count);Expected output
5
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 What does ts.forEachChild(node, fn) do?
- Mutates the node's text
- Visits every child of a node in order Correct answer
- Performs type checking
- Creates a new AST node
Explanation: forEachChild passes each direct child of a node in order to the given function; it neither creates nodes nor mutates text.
2 Identifier text
function visit(node: ts.Node) {
if (ts.isIdentifier(node)) {
console.log(node.____);
}
ts.forEachChild(node, visit);
}
function visit(node: ts.Node) {
if (ts.isIdentifier(node)) {
console.log(node.text);
}
ts.forEachChild(node, visit);
}
Explanation: Identifier.text gives the textual value of the identifier; the Identifier node has no name, value or key property.
3 AST visit parts
| Term | Meaning |
|---|---|
ts.forEachChild |
Walks child nodes |
node.kind |
Node kind number |
ts.SyntaxKind[kind] |
Gives the kind name |
ts.isIdentifier(node) |
Whether the node is an Identifier |