Optimizing Claude Code for Large Scale Refactoring in TypeScript Projects
// ... rest of the code comments instead of writing full implementations. If you're trying to migrate a massive set of interfaces or change a core data model across 50+ files, you can't just tell it to "refactor the project." You'll end up with a broken build and half-finished files.My current workflow relies on a "Map-Reduce" approach to refactoring. Instead of letting the AI wander, I force it to build a dependency map first.
First, I use a strict prompt to identify the blast radius. I don't let it touch code until it lists every file that will be affected. This prevents it from missing an edge-case import that would otherwise cause a TS error later.
# Start by mapping the impact
claude "Find all files that import the UserProfile interface from @/types/user.ts and list them. Do not modify anything yet."Once I have the list, the secret to avoiding the "lazy" ellipses is to constrain the scope per turn. I've found that if you ask Claude Code to handle more than 3-5 files in one go, the quality of the TypeScript types drops. I now use a loop-style prompting strategy: "Refactor the following 3 files [list files], ensuring all Type guards are updated. Provide the full file content."
To keep the TS compiler happy, I integrate the tsc check directly into the loop. I don't trust the AI's claim that "the code is now correct." I make it run the compiler and fix its own mistakes.
# Example of a verification loop
claude "Refactor the API handlers in /src/api/v1 to use the new ResponseWrapper. After editing, run 'npm run type-check' and fix any resulting TypeScript errors until the command passes."One major gotcha with Claude Code in TS projects is its tendency to over-simplify types to any or unknown when it hits a complex generic it doesn't fully understand from the provided context. To fight this, I added a .claudecode.config (or a project-level .cursorrules equivalent) that explicitly forbids any.
My current "No-Lazy" rules for TS refactoring:
- Strict Typing: Never use
any. If a type is unknown, use a genericTor a specific Union type. - Full Implementation: Never use comments like
// ... existing logicto skip code. Always output the complete function body. - Import Optimization: Always run the project's linting tool after a refactor to clean up unused imports created during the move.
Another productivity gain comes from using the
@ symbol effectively to feed it the specific type definitions it needs. If I'm refactoring a service, I explicitly feed it the related DTOs and Interface files as context first, then give the command to edit the service. This reduces the "hallucinated property" bug where Claude assumes a property exists on an object just because it sounds logical.For those dealing with massive monorepos, avoid running Claude Code from the root if the refactor is localized. Navigate to the specific package folder. It reduces the noise in the file tree and makes the tool significantly faster at indexing the relevant symbols.
All Replies (0)
No replies yet — be the first!
