How to use Windsurf Flow for complex multi-file refactoring in TypeScript
The biggest mistake most people make is giving Flow a generic prompt like "refactor these files to use Zod." That usually leads to hallucinated types or missing imports. Instead, I treat the first prompt as a "Discovery Phase."
I start by forcing Windsurf to map out the blast radius. My go-to prompt for this is:
Analyze the current implementation of the UserProfile service and all files that import its types. List every file that will be affected if I change the return type of fetchUser to a Zod schema. Do not make changes yet; just provide the file list and the specific lines that will break.Once it lists the files, I switch to the execution phase. The trick here is to use "incremental constraints." Instead of letting it loose on five files at once, I tell it to follow a specific sequence: Schema definition -> Type updates -> Implementation change -> Consumer updates.
For example, when I was moving from any to strict interfaces in a complex Redux slice, I used this workflow:
1. Establish the Truth
I point it to the source of truth first.
In @types/user.ts, define the Zod schema for UserProfile. Use this as the single source of truth for all subsequent changes in this flow.2. The Cascade Update
Now that the schema exists, I let Flow propagate the changes. Because it's in Flow mode, it can jump between the service file and the component files automatically.
Update the API client to validate responses with the new Zod schema. Then, find all components using these types and update their TypeScript interfaces to match the inferred Zod type. Fix any resulting type errors in the JSX.A few productivity gains I've noticed:
- Context Pinning: If Flow starts drifting or forgets a specific edge case (like a weird null check in a helper function), I explicitly mention the file path again. It resets its focus on that specific AST node.
- The "Dry Run" Loop: I always check the
git diffafter a major Flow sequence. If it over-refactored (e.g., changed a variable name it wasn't asked to), I use a prompt likeRevert the renaming of 'userData' to 'user' in profile.tsx, but keep the type changes.
Gotchas to watch out for:
- Circular Dependencies: TypeScript circular imports can confuse the agent. If you see it looping between two files without making progress, manually break the cycle or tell it to
Ignore the circular dependency in X for now and focus on the type definition in Y. - Implicit Any: Sometimes Flow will "fix" a type error by adding
anyjust to make the red squiggly go away. I've added a global rule to my project.windsurfconfig (or just as a prefix to my prompts) that saysAvoid using 'any' at all costs; prefer 'unknown' or a generic if the type is truly dynamic.
This approach turns refactoring from a "pray and compile" experience into a structured migration. You're essentially using the AI as a high-speed navigator that can actually read the whole map, rather than just a fancy typewriter.
All Replies (0)
No replies yet — be the first!
