Introduction
ts-morph provides a simplified, well-documented wrapper around the TypeScript compiler API. Where the raw compiler API requires deep knowledge of AST node kinds and manual navigation, ts-morph offers a fluent interface with methods like getClasses(), getInterfaces(), and rename() that make code analysis and transformation accessible to any TypeScript developer.
What ts-morph Does
- Provides a high-level API over the TypeScript compiler for reading and modifying source files
- Enables programmatic refactoring: renaming symbols, moving declarations, adding or removing code
- Supports full type-checking integration for type-aware code analysis
- Manages an in-memory file system that tracks changes before writing to disk
- Handles formatting and import organization automatically after transformations
Architecture Overview
ts-morph wraps the TypeScript compiler's Program, SourceFile, and Node types with wrapper classes that expose navigation and manipulation methods. An in-memory file system (virtual or real) holds source files, and a Project instance manages compilation settings and file resolution. When modifications are made, ts-morph updates the underlying AST and tracks dirty files. Calling save writes only changed files to disk.
Self-Hosting & Configuration
- Install as a dev dependency:
npm install --save-dev ts-morph - Create a Project with
new Project({ tsConfigFilePath: "./tsconfig.json" })to inherit compiler settings - Add files explicitly with
project.addSourceFilesAtPaths(["src/**/*.ts"])or let the tsconfig resolve them - Use
project.createSourceFile("path.ts", code)to generate new files programmatically - Configure compiler options directly:
new Project({ compilerOptions: { strict: true } })
Key Features
- Fluent navigation:
sourceFile.getClasses(),classDecl.getMethods(),method.getParameters() - Type-aware analysis:
node.getType().getText()returns the resolved TypeScript type as a string - Safe refactoring:
identifier.rename("newName")updates all references across the project - Code generation: build classes, interfaces, and functions programmatically with builder APIs
- Format preservation: untouched code retains its original formatting
Comparison with Similar Tools
- TypeScript Compiler API — The raw API ts-morph wraps; powerful but verbose with poor discoverability
- jscodeshift — Parser-agnostic codemod runner; ts-morph provides tighter TypeScript integration with type information
- ast-grep — Pattern-based search and replace; ts-morph offers full programmatic control with TypeScript semantics
- Babel — Targets JavaScript transformation during builds; ts-morph works with TypeScript types and project-wide refactoring
- ESLint custom rules — Good for enforcing patterns; ts-morph handles complex multi-file transformations beyond lint scope
FAQ
Q: Is ts-morph suitable for large codebases?
A: Yes. It uses the same compiler infrastructure as TypeScript itself. For very large projects, you can limit loaded files or use the project.getSourceFile() method to work with specific files.
Q: Can ts-morph modify JavaScript files?
A: Yes. Set allowJs: true in compiler options. JavaScript files are parsed and wrapped the same way, though type information will be limited.
Q: Does ts-morph preserve comments and formatting? A: It preserves formatting for untouched code. Modified or inserted code uses the project's formatting settings. Comments attached to moved nodes are preserved.
Q: How do I use ts-morph for code generation?
A: Use sourceFile.addClass({ name: "MyClass", methods: [...] }) or sourceFile.addStatements("const x = 1;") to build code programmatically with full type safety.