skills/claudeception/examples/typescript-circular-dependency/SKILL.md
Detect and resolve TypeScript/JavaScript circular import dependencies. Use when: (1) "Cannot access 'X' before initialization" at runtime, (2) Import returns undefined unexpectedly, (3) "ReferenceError: Cannot access X before initialization", (4) Type errors that disappear when you change import order, (5) Jest/Vitest tests fail with undefined imports that work in browser.
npx skillsauth add aresbit/matebot typescript-circular-dependencyInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Circular dependencies occur when module A imports from module B, which imports
(directly or indirectly) from module A. TypeScript compiles successfully, but at
runtime, one of the imports evaluates to undefined because the module hasn't
finished initializing yet.
Common error messages:
ReferenceError: Cannot access 'UserService' before initialization
TypeError: Cannot read properties of undefined (reading 'create')
TypeError: (0 , _service.doSomething) is not a function
Symptoms that suggest circular imports:
undefined even though the export existsconsole.log at the top of a file changes behaviorUse a tool to visualize dependencies:
# Install madge
npm install -g madge
# Find circular dependencies
madge --circular --extensions ts,tsx src/
# Generate visual graph
madge --circular --image graph.svg src/
Or use the TypeScript compiler:
# Check for cycles (requires tsconfig setting)
npx tsc --listFiles | head -50
Common circular dependency patterns:
Pattern A: Service-to-Service
services/userService.ts → services/orderService.ts → services/userService.ts
Pattern B: Type imports
types/user.ts → types/order.ts → types/user.ts
Pattern C: Index barrel files
components/index.ts → components/Button.tsx → components/index.ts
Strategy 1: Extract Shared Dependencies
Before:
// userService.ts
import { OrderService } from './orderService';
export class UserService { ... }
// orderService.ts
import { UserService } from './userService';
export class OrderService { ... }
After:
// types/interfaces.ts (new file - no imports from services)
export interface IUserService { ... }
export interface IOrderService { ... }
// userService.ts
import { IOrderService } from '../types/interfaces';
export class UserService implements IUserService { ... }
Strategy 2: Dependency Injection
// orderService.ts
export class OrderService {
constructor(private userService: IUserService) {}
// Instead of importing UserService directly
}
// main.ts
const userService = new UserService();
const orderService = new OrderService(userService);
Strategy 3: Dynamic Imports
// Only import when needed, not at module level
async function processOrder() {
const { UserService } = await import('./userService');
// ...
}
Strategy 4: Use Type-Only Imports
If you only need types (not values), use type-only imports:
// This doesn't create a runtime dependency
import type { User } from './userService';
Strategy 5: Restructure Barrel Files
Before (problematic):
// components/index.ts
export * from './Button';
export * from './Modal'; // Modal imports Button from './index'
After:
// components/Modal.tsx
import { Button } from './Button'; // Direct import, not from index
Add to your CI/build process:
// package.json
{
"scripts": {
"check:circular": "madge --circular --extensions ts,tsx src/"
}
}
Or configure ESLint:
// .eslintrc.js
module.exports = {
plugins: ['import'],
rules: {
'import/no-cycle': ['error', { maxDepth: 10 }]
}
}
madge --circular src/ - should report no cyclesnode_modules and reinstall - app should still workProblem: OrderService is undefined when imported in UserService
Detection:
$ madge --circular src/
Circular dependencies found!
src/services/userService.ts → src/services/orderService.ts → src/services/userService.ts
Fix: Extract shared interface
// NEW: src/types/services.ts
export interface IOrderService {
createOrder(userId: string): Promise<Order>;
}
// MODIFIED: src/services/userService.ts
import type { IOrderService } from '../types/services';
export class UserService {
constructor(private orderService: IOrderService) {}
}
// MODIFIED: src/services/orderService.ts
// No longer imports UserService
export class OrderService implements IOrderService {
async createOrder(userId: string): Promise<Order> { ... }
}
import type is your friend—it's erased at runtime and can't cause cyclesindex.ts) are a common source of accidental cyclesrequire() can sometimes mask circular dependency issues that import exposesdocumentation
Generate and edit Word documents (.docx). Supports professional documents including covers, charts, track-changes editing, and more. Suitable for any .docx creation or modification task.
tools
--- name: discord description: Use when you need to control Discord from OpenClaw via the discord tool: send messages, react, post or upload stickers, upload emojis, run polls, manage threads/pins/search, create/edit/delete channels and categories, fetch permissions or member/role/channel info, or handle moderation actions in Discord DMs or channels. metadata: {"openclaw":{"emoji":"🎮","requires":{"config":["channels.discord"]}}} --- # Discord Actions ## Overview Use `discord` to manage messa
tools
Run Codex CLI, Claude Code, OpenCode, or Pi Coding Agent via background process for programmatic control.
tools
Use the ClawdHub CLI to search, install, update, and publish agent skills from clawdhub.com. Use when you need to fetch new skills on the fly, sync installed skills to latest or a specific version, or publish new/updated skill folders with the npm-installed clawdhub CLI.