What is ts-morph?
The ts-morph package is a TypeScript compiler API wrapper that provides a simpler way to programmatically navigate, analyze, and manipulate TypeScript and JavaScript code. It abstracts the complexity of the underlying TypeScript compiler API, making it more accessible and easier to use for tasks such as code analysis, transformation, and generation.
What are ts-morph's main functionalities?
Navigating the AST
This feature allows users to navigate the Abstract Syntax Tree (AST) of a TypeScript file. The code sample demonstrates how to load a TypeScript file into a project, retrieve all classes from it, and log their names.
const project = new Project();
const sourceFile = project.addSourceFileAtPath('example.ts');
const classes = sourceFile.getClasses();
console.log(classes.map(c => c.getName()));
Modifying code
This feature enables users to programmatically modify TypeScript code. The code sample shows how to create a new TypeScript file, change the initializer of a variable declaration, and then log the updated source code.
const project = new Project();
const sourceFile = project.createSourceFile('example.ts', 'const a = 1;');
sourceFile.getVariableDeclaration('a').setInitializer('2');
console.log(sourceFile.getText());
Code generation
This feature is used for generating new code, such as classes, interfaces, or functions. The code sample illustrates how to create a new TypeScript file and add a new class to it.
const project = new Project();
const sourceFile = project.createSourceFile('example.ts');
sourceFile.addClass({ name: 'NewClass' });
console.log(sourceFile.getText());
Other packages similar to ts-morph
typescript
The 'typescript' package is the core TypeScript compiler itself. While ts-morph is built on top of it and provides a higher-level API for easier manipulation of TypeScript code, using the 'typescript' package directly requires more in-depth knowledge of the TypeScript compiler API.
jscodeshift
jscodeshift is a toolkit for running codemods over multiple JavaScript or TypeScript files. It provides a more scriptable interface for transforming code. Compared to ts-morph, jscodeshift is more focused on code transformations and less on detailed AST navigation or code generation.
babel
Babel is a widely used JavaScript compiler that allows developers to use next-generation JavaScript, today. It can be used for code transformations similar to ts-morph, but it's more focused on compiling modern JavaScript syntax to backwards-compatible versions. Babel's plugin system allows for powerful code transformations but requires more setup compared to ts-morph for TypeScript-specific tasks.
ts-morph
TypeScript Compiler API wrapper. Provides an easier way to programmatically navigate and manipulate TypeScript and JavaScript code.
Formerly ts-simple-ast
.
Overview
Main Features
- Wraps the compiler API objects to provide helper methods for getting information and programmatically changing files.
- Allows falling back to the compiler API objects if necessary (ex.
classDeclaration.compilerNode
or typeChecker.compilerObject
). - All changes are kept in memory (including file and directory moves) until specifying to save to the underlying file system.
- Changes are made to the text and wrapped nodes can be held onto between manipulations.
Getting Started
- Installing
- Instantiating
- Adding source files
- Getting source files
- Navigating
- Manipulating
Library Progress
This library is still under active development. Most common code manipulation/generation use cases are implemented, but there's still a lot of work to do. Please open an issue if you find a feature missing, bug, or question that isn't in the issue tracker.
Example
import { Project, StructureKind } from "ts-morph";
const project = new Project({
});
project.addSourceFilesAtPaths("src/**/*.ts");
const myClassFile = project.createSourceFile("src/MyClass.ts", "export class MyClass {}");
const myEnumFile = project.createSourceFile("src/MyEnum.ts", {
statements: [{
kind: StructureKind.Enum,
name: "MyEnum",
isExported: true,
members: [{ name: "member" }],
}],
});
const myClass = myClassFile.getClassOrThrow("MyClass");
myClass.getName();
myClass.hasExportKeyword();
myClass.isDefaultExport();
const myInterface = myClassFile.addInterface({
name: "IMyInterface",
isExported: true,
properties: [{
name: "myProp",
type: "number",
}],
});
myClass.rename("NewName");
myClass.addImplements(myInterface.getName());
myClass.addProperty({
name: "myProp",
initializer: "5",
});
project.getSourceFileOrThrow("src/ExistingFile.ts").delete();
await project.save();
const compilerNode = myClassFile.compilerNode;
Or navigate existing compiler nodes created with the TypeScript compiler (the ts
named export is the TypeScript compiler):
import { createWrappedNode, ClassDeclaration, ts } from "ts-morph";
const classNode: ts.ClassDeclaration = ...;
const classDec = createWrappedNode(classNode) as ClassDeclaration;
const firstProperty = classDec.getProperties()[0];