Skip to content

What is codeanalyzer-typescript?

codeanalyzer-typescript is a static-analysis tool for TypeScript and JavaScript source code. You point it at a project directory and it produces one typed artifact — a TSApplication — that captures the project’s symbol table (modules, classes, interfaces, enums, type aliases, callables), its call graph (who-calls-whom), and the external symbols it reaches (phantom stubs for imported-library targets). You stop grepping source by hand and start querying a structured model of the program.

It is the TypeScript backend behind CLDK, the multilingual analysis SDK — the same role codeanalyzer-python and codeanalyzer play for Python and Java. You can use it through CLDK’s typed facade, or directly as a CLI that writes analysis.json.

Every run follows the same shape: point at a project, build the artifact, consume the typed model.

  1. Point at a project. codeanalyzer-typescript --input ./my-project. The tool discovers every .ts/.tsx/.js file (test trees excluded by default) and, by default, materializes the project’s node_modules so the compiler can resolve imported types and call targets.

  2. It builds a TSApplication. The TypeScript compiler — driven through ts-morph — extracts the symbol table; the same checker resolves each call site into the call graph, with Rapid Type Analysis expanding virtual dispatch and phantom nodes capturing external calls.

  3. Consume the typed model. Get analysis.json (or msgpack) on disk, or pipe the JSON straight to jq. Everything is one typed document: symbol_table, call_graph, external_symbols, entrypoints.

flowchart LR
    A["codeanalyzer-typescript
--input"] --> B["materialize
node_modules"]
    B --> C[Symbol table<br/>ts-morph checker]
    C --> D[Call graph<br/>resolver + RTA]
    D --> E[External symbols<br/>phantom nodes]
    D -.->|-a 2| F[CodeQL edges]
    E --> G["TSApplication
analysis.json / msgpack"]
    F -.-> G

The artifact is a single TSApplication with four top-level pieces:

FieldTypeWhat it holds
symbol_tableRecord<string, TSModule>One TSModule per source file — its imports, exports, classes, interfaces, enums, type aliases, functions, namespaces, and variables.
call_graphTSCallEdge[]Identity-keyed source -> target edges (by TSCallable.signature) with a weight, provenance, and tags.
external_symbolsRecord<string, TSExternalSymbol>Phantom stubs for call targets outside the project — imported libraries and Node builtins.
entrypointsRecord<string, TSEntrypoint[]>Framework-dispatched roots, keyed by framework name. Empty at level 1.

A single canonicalizer, signatureOf, computes both caller- and callee-side identifiers, so a call graph source/target value byte-matches the corresponding symbol_table (or external_symbols) key. A signature is the project-relative file path (without extension) dot-joined with the member path — e.g. src/user.UserService.getUser. Constructors normalize to <ClassSignature>.constructor. See Core concepts.

Terminal window
# Write analysis.json to ./out
codeanalyzer-typescript --input ./my-project --output ./out
# Or stream JSON to stdout (no --output)
codeanalyzer-typescript --input ./my-project | jq '.call_graph | length'

A code LLM asked “what calls this function?” without analysis crawls: file read after file read, grep after grep, burning tokens on an answer it still can’t be sure of. codeanalyzer-typescript resolves that once, statically, into a graph — so the answer is a lookup, not a guess. The TypeScript compiler gives you precise resolution for free on every run; RTA recovers the virtual-dispatch targets a naive resolver would miss; phantom nodes keep the calls into third-party libraries visible instead of silently dropped.