TypeScript compiler wrapper for static analysis and code manipulation.
—
Comprehensive file system operations and directory management capabilities integrated with the project structure. Provides seamless integration between TypeScript code manipulation and file system operations.
Represents a directory within the project with full manipulation capabilities.
class Directory {
/** Get the directory name */
getName(): string;
/** Get the full path */
getPath(): string;
/** Get the base name (same as getName) */
getBaseName(): string;
/** Get the parent directory */
getParent(): Directory | undefined;
/** Get all child directories */
getDirectories(): Directory[];
/** Get a child directory by name */
getDirectory(name: string): Directory | undefined;
/** Get a child directory by name, throwing if not found */
getDirectoryOrThrow(name: string): Directory;
/** Get all source files in this directory */
getSourceFiles(): SourceFile[];
/** Get a source file by name */
getSourceFile(name: string): SourceFile | undefined;
/** Get a source file by name, throwing if not found */
getSourceFileOrThrow(name: string): SourceFile;
/** Create a child directory */
createDirectory(name: string): Directory;
/** Create a source file in this directory */
createSourceFile(fileName: string, text?: string, options?: SourceFileCreateOptions): SourceFile;
/** Add an existing source file to this directory */
addSourceFileAtPath(filePath: string): SourceFile;
/** Add an existing source file to this directory if it exists */
addSourceFileAtPathIfExists(filePath: string): SourceFile | undefined;
/** Add existing source files matching a glob pattern */
addSourceFilesAtPaths(fileGlobs: string | string[]): SourceFile[];
/** Copy this directory to a new location */
copy(dirPath: string, options?: DirectoryCopyOptions): Directory;
/** Move this directory to a new location */
move(dirPath: string, options?: DirectoryMoveOptions): Directory;
/** Delete this directory */
delete(): void;
/** Check if this directory exists on the file system */
exists(): boolean;
/** Check if this directory exists on the file system asynchronously */
existsAsync(): Promise<boolean>;
/** Emit all TypeScript files in this directory */
emit(options?: { emitOnlyDtsFiles?: boolean }): Promise<DirectoryEmitResult>;
/** Emit all TypeScript files in this directory synchronously */
emitSync(options?: { emitOnlyDtsFiles?: boolean }): DirectoryEmitResult;
/** Save all unsaved source files in this directory */
save(): Promise<void>;
/** Save all unsaved source files in this directory synchronously */
saveSync(): void;
/** Get descendants (all nested directories and files) */
getDescendants(): (Directory | SourceFile)[];
/** Get descendant directories */
getDescendantDirectories(): Directory[];
/** Get descendant source files */
getDescendantSourceFiles(): SourceFile[];
}
interface DirectoryCopyOptions {
/** Whether to overwrite existing files */
overwrite?: boolean;
/** Whether to include directories */
includeUntrackedFiles?: boolean;
}
interface DirectoryMoveOptions {
/** Whether to overwrite existing files */
overwrite?: boolean;
}
interface DirectoryAddOptions {
/** Whether to recursively add subdirectories */
recursive?: boolean;
}Result of emitting TypeScript files in a directory.
class DirectoryEmitResult {
/** Get all emit results for files in the directory */
getEmitResults(): EmitResult[];
/** Check if any emits were skipped */
getEmitSkipped(): boolean;
/** Get all diagnostics from the emit operation */
getDiagnostics(): Diagnostic[];
/** Get output file paths that were created */
getOutputFilePaths(): string[];
}Interface for custom file system implementations.
interface FileSystemHost {
/** Check if a file or directory exists */
exists(path: string): boolean;
/** Check if a file or directory exists asynchronously */
existsAsync(path: string): Promise<boolean>;
/** Read a file as text */
readFileSync(path: string, encoding?: string): string;
/** Read a file as text asynchronously */
readFile(path: string, encoding?: string): Promise<string>;
/** Write text to a file */
writeFileSync(path: string, data: string): void;
/** Write text to a file asynchronously */
writeFile(path: string, data: string): Promise<void>;
/** Create a directory */
mkdirSync(path: string): void;
/** Create a directory asynchronously */
mkdir(path: string): Promise<void>;
/** Delete a file or directory */
deleteSync(path: string): void;
/** Delete a file or directory asynchronously */
delete(path: string): Promise<void>;
/** Get directory entries */
readDirSync(path: string): RuntimeDirEntry[];
/** Copy a file */
copySync(srcPath: string, destPath: string): void;
/** Copy a file asynchronously */
copy(srcPath: string, destPath: string): Promise<void>;
/** Move a file */
moveSync(srcPath: string, destPath: string): void;
/** Move a file asynchronously */
move(srcPath: string, destPath: string): Promise<void>;
/** Get file or directory stats */
statSync(path: string): StatSync;
/** Get file or directory stats asynchronously */
stat(path: string): Promise<Stat>;
/** Resolve a path */
realPathSync(path: string): string;
/** Get current working directory */
getCurrentDirectory(): string;
/** Get the path separator */
getPathSeparator(): string;
}
interface RuntimeDirEntry {
name: string;
isFile(): boolean;
isDirectory(): boolean;
isSymlink(): boolean;
}
interface StatSync {
isFile(): boolean;
isDirectory(): boolean;
size: number;
mtimeMs: number;
}
interface Stat {
isFile(): boolean;
isDirectory(): boolean;
size: number;
mtimeMs: number;
}Built-in in-memory file system implementation for testing and virtual file operations.
class InMemoryFileSystemHost implements FileSystemHost {
/** Create a new in-memory file system */
constructor();
/** Get all files and directories in memory */
getFiles(): { path: string; text: string }[];
/** Clear all files and directories */
clear(): void;
/** Get a file's text content */
getFileText(path: string): string;
/** Check if path is a directory */
isDirectory(path: string): boolean;
/** Check if path is a file */
isFile(path: string): boolean;
// ... implements all FileSystemHost methods
}Extended file operations available on SourceFile instances.
interface SourceFileCopyOptions {
/** Whether to overwrite if the target exists */
overwrite?: boolean;
}
interface SourceFileMoveOptions {
/** Whether to overwrite if the target exists */
overwrite?: boolean;
}
// Additional SourceFile methods for file system operations
class SourceFile extends Node {
/** Get the directory containing this source file */
getDirectory(): Directory;
/** Get the directory path */
getDirectoryPath(): string;
/** Check if the file is in a node_modules directory */
isInNodeModules(): boolean;
/** Check if this is a declaration file (.d.ts) */
isDeclarationFile(): boolean;
/** Check if the file has been modified */
isModified(): boolean;
/** Get the last modified time */
getModifiedTime(): Date;
/** Refresh from file system */
refreshFromFileSystemSync(): this;
/** Refresh from file system asynchronously */
refreshFromFileSystem(): Promise<this>;
/** Get referenced files */
getReferencedFiles(): SourceFile[];
/** Get files that reference this file */
getReferencingSourceFiles(): SourceFile[];
/** Get files that reference this file (including library files) */
getReferencingNodesInOtherSourceFiles(): SourceFileReferencingNodes[];
/** Get the relative path from another source file */
getRelativePathTo(sourceFile: SourceFile): string;
/** Get the relative path from a directory */
getRelativePathToDirectory(directory: Directory): string;
}
interface SourceFileReferencingNodes {
sourceFile: SourceFile;
nodes: Node[];
}Usage Examples:
import { Project, InMemoryFileSystemHost } from "ts-morph";
// Working with the default file system
const project = new Project();
// Add a directory
const srcDir = project.createDirectory("src");
const utilsDir = srcDir.createDirectory("utils");
// Create files in directories
const indexFile = srcDir.createSourceFile("index.ts", `
export { Logger } from './utils/logger';
export { Calculator } from './utils/calculator';
`);
const loggerFile = utilsDir.createSourceFile("logger.ts", `
export class Logger {
log(message: string): void {
console.log(message);
}
}
`);
const calculatorFile = utilsDir.createSourceFile("calculator.ts", `
export class Calculator {
add(a: number, b: number): number {
return a + b;
}
multiply(a: number, b: number): number {
return a * b;
}
}
`);
// Work with directories
console.log("Source directory name:", srcDir.getName());
console.log("Source directory path:", srcDir.getPath());
// Get files and subdirectories
const srcFiles = srcDir.getSourceFiles();
console.log("Files in src:", srcFiles.map(f => f.getBaseName()));
const subdirs = srcDir.getDirectories();
console.log("Subdirectories:", subdirs.map(d => d.getName()));
// Get all descendant files
const allFiles = srcDir.getDescendantSourceFiles();
console.log("All files recursively:", allFiles.map(f => f.getBaseName()));
// File operations
const backupDir = project.createDirectory("backup");
loggerFile.copy("backup/logger-backup.ts");
// Directory operations
const utilsCopy = utilsDir.copy("src/utils-backup");
console.log("Copied utils to:", utilsCopy.getPath());
// Save all files
project.saveSync();
// Emit TypeScript files
const emitResult = await srcDir.emit();
console.log("Emit successful:", !emitResult.getEmitSkipped());
console.log("Output files:", emitResult.getOutputFilePaths());Working with In-Memory File System:
import { Project, InMemoryFileSystemHost } from "ts-morph";
// Create project with in-memory file system
const fileSystem = new InMemoryFileSystemHost();
const project = new Project({
fileSystem,
useInMemoryFileSystem: true,
});
// Create virtual files
const sourceFile = project.createSourceFile("/virtual/app.ts", `
class VirtualApp {
run(): void {
console.log('Running in memory!');
}
}
`);
// Work with virtual directories
const virtualDir = project.createDirectory("/virtual");
const configFile = virtualDir.createSourceFile("config.ts", `
export const config = {
port: 3000,
host: 'localhost'
};
`);
// Check file system state
console.log("Virtual files:", fileSystem.getFiles());
// The files exist only in memory
console.log("App file exists:", fileSystem.exists("/virtual/app.ts"));
console.log("App file content:", fileSystem.getFileText("/virtual/app.ts"));
// Clear the virtual file system
fileSystem.clear();
console.log("Files after clear:", fileSystem.getFiles());Advanced File System Operations:
import { Project } from "ts-morph";
const project = new Project();
// Add files from glob patterns
const srcDir = project.createDirectory("src");
srcDir.addSourceFilesAtPaths(["**/*.ts", "!**/*.test.ts"]);
// Get file relationships
const indexFile = srcDir.getSourceFile("index.ts");
if (indexFile) {
// Get files that this file references
const referenced = indexFile.getReferencedFiles();
console.log("Referenced files:", referenced.map(f => f.getFilePath()));
// Get files that reference this file
const referencing = indexFile.getReferencingSourceFiles();
console.log("Files referencing index:", referencing.map(f => f.getFilePath()));
// Get relative paths
const utilsFile = srcDir.getSourceFile("utils/helper.ts");
if (utilsFile) {
const relativePath = indexFile.getRelativePathTo(utilsFile);
console.log("Relative path to utils:", relativePath);
}
}
// Monitor file changes
const watchedFile = srcDir.getSourceFile("watched.ts");
if (watchedFile) {
const initialModTime = watchedFile.getModifiedTime();
// Modify the file
watchedFile.addClass({ name: "NewClass" });
// Check if modified
console.log("File is modified:", watchedFile.isModified());
console.log("Modified time changed:",
watchedFile.getModifiedTime() > initialModTime);
}
// Batch operations on directories
const testDir = project.createDirectory("tests");
// Create multiple test files
const testFiles = [
"user.test.ts",
"auth.test.ts",
"api.test.ts"
].map(name => testDir.createSourceFile(name, `
describe('${name.replace('.test.ts', '')}', () => {
test('should work', () => {
expect(true).toBe(true);
});
});
`));
// Save all test files at once
await testDir.save();
// Emit only declaration files
const emitResult = await testDir.emit({ emitOnlyDtsFiles: true });
console.log("Declaration files emitted:", emitResult.getOutputFilePaths());Install with Tessl CLI
npx tessl i tessl/npm-ts-morph