# 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.

```bash
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`.

```typescript
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.

```typescript
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:**
```text
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.

```typescript
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.

```typescript
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`.

```typescript
const program = ts.createProgram(["example.ts"], {});
const checker = program.getTypeChecker();

// You would then traverse source files from program.getSourceFiles()
// and use checker.getTypeAtLocation(node)
```

[[programming/javascript/typescript/typescript]]