Source Refactoring Skill
What This Skill Does
Provides guidance on splitting existing code (functions, components, hooks) into separate files while maintaining project standards:
- One function per file - By default, extract each function into its own dedicated file.
- Single Symbol Exports - Use
export defaultwhen a file only exports one main symbol. - Naming Conventions:
- Single-symbol files: Name the file after the symbol (e.g.,
camelCase.tsfor functions,PascalCase.tsxfor components). - Multi-symbol files: Use
kebab-case.tsfor files that must export multiple symbols.
- Single-symbol files: Name the file after the symbol (e.g.,
- JSDoc Preservation - Carry over existing documentation and JSDoc comments.
- Test Colocation - Move and refactor unit tests into a new
*.test.tsor*.test.tsxfile next to the new source file. - Import Management - Update all references to the moved symbol across the codebase.
When to Use
- When a file grows too large and needs splitting.
- When extracting a utility function or component for better reuse.
- When moving logic out of a component into a specialized hook or service.
Key Rules
1. Default Export for Single Symbols
If the new file only exports one main function or component, use export default:
// ✅ GOOD: Single exported function
/**
* @param value - The value to check
* @returns True if value is a record
*/
export default function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null && !Array.isArray(value);
}
If the file needs to export multiple related symbols (e.g., related types or small helpers that don't merit their own files), use named exports or a combination:
// ✅ GOOD: Multiple related exports
export type FooProps = { ... };
export function Foo() { ... }
Note: If the file ONLY exports one thing, it MUST be export default.
2. Preserve JSDoc
Always copy the JSDoc comments from the original file to the new file. Ensure parameters and return descriptions are accurate. Do not include types in JSDoc for TypeScript files.
3. Move and Refactor Tests
If the symbol being moved has existing tests, they must be moved to a new test file colocated with the source.
- Create
NewFile.test.tsnext toNewFile.ts. - Move relevant
it/describeblocks from the old test file to the new one. - Update imports in the new test file to point to the new location.
- Update imports in the old test file if it still needs other symbols.
- Remove the moved tests from the old test file.
- Run the tests to ensure everything still passes.
4. Update References
Search the codebase for all occurrences of the moved symbol and update their imports.
- If switching from a named export in a multi-symbol file to a default export in a new file, change
import { symbol } from './Original'toimport symbol from './New'.
Step-by-Step Refactoring Process
- Identify the target: Select the function or component to split off.
- Create the new file: Create
NewFile.tsxorNewFile.tsin the appropriate directory. - Copy logic and JSDoc: Transfer the code and its comments. Use
export defaultif it's the only export. - Locate tests: Find the existing tests for the symbol (usually in
OriginalFile.test.ts). - Split tests: Move the tests to
NewFile.test.ts. - Update imports: Use
grep_searchorsemantic_searchto find all usages and update imports. - Verify: Run
npm run lintandnpm run test:unit -- <NewFile>.test.tsto confirm the change is correct.
