TypeScript Compiler API Basics
The TypeScript Compiler API allows you to interact with the TypeScript compiler programmatically. You can use it to parse code into an Abstract Syntax Tree (AST), inspect types, transform code, and generate output. This is the foundation for tools like linters, formatters, and custom transformers.
1. Installation
You just need the standard typescript package.
npm install typescript
npm install --save-dev @types/node
2. Parsing Code (Creating an AST)
To analyze code, you first need to parse it into a SourceFile.
import * as ts from "typescript";
const sourceCode = `
class Greeter {
greet() {
console.log("Hello, world!");
}
}
`;
const sourceFile = ts.createSourceFile(
"example.ts", // File name (virtual)
sourceCode, // Source code string
ts.ScriptTarget.Latest, // Language version
true // setParentNodes (useful for traversal)
);
3. Traversing the AST
Once you have a SourceFile, you can traverse it to inspect nodes. TypeScript provides ts.forEachChild to iterate over child nodes efficiently.
function printRecursive(node: ts.Node, indent: number = 0) {
const indentation = " ".repeat(indent);
const syntaxKind = ts.SyntaxKind[node.kind];
console.log(`${indentation}${syntaxKind}`);
// Recurse into children
ts.forEachChild(node, child => printRecursive(child, indent + 1));
}
printRecursive(sourceFile);
Output:
SourceFile
ClassDeclaration
Identifier
MethodDeclaration
Identifier
Block
ExpressionStatement
CallExpression
PropertyAccessExpression
Identifier
Identifier
StringLiteral
EndOfFileToken
4. Inspecting Nodes
You can cast nodes to specific interfaces to access their properties.
function analyzeNode(node: ts.Node) {
if (ts.isClassDeclaration(node)) {
// node is now typed as ts.ClassDeclaration
if (node.name) {
console.log(`Found class: ${node.name.text}`);
}
}
ts.forEachChild(node, analyzeNode);
}
analyzeNode(sourceFile);
5. Creating/Printing Code
You can also generate code programmatically using factory functions and the Printer API.
const factory = ts.factory;
// Create: const x = 42;
const statement = factory.createVariableStatement(
undefined,
factory.createVariableDeclarationList(
[
factory.createVariableDeclaration(
factory.createIdentifier("x"),
undefined,
undefined,
factory.createNumericLiteral(42)
)
],
ts.NodeFlags.Const
)
);
const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
const result = printer.printNode(
ts.EmitHint.Unspecified,
statement,
sourceFile // used for context (indentation, etc)
);
console.log(result); // const x = 42;
6. Type Checking (Advanced)
To inspect semantic information (types, symbols), you need to create a ts.Program.
const program = ts.createProgram(["example.ts"], {});
const checker = program.getTypeChecker();
// You would then traverse source files from program.getSourceFiles()
// and use checker.getTypeAtLocation(node)