Skip to main content
This page extends Common Rules with TypeScript/JavaScript specific content.Applies to: **/*.ts, **/*.tsx, **/*.js, **/*.jsx

Coding Style

Immutability

Use spread operator for immutable updates:
function updateUser(user, name) {
  user.name = name  // MUTATION!
  return user
}

Error Handling

Use async/await with try-catch:
try {
  const result = await riskyOperation()
  return result
} catch (error) {
  console.error('Operation failed:', error)
  throw new Error('Detailed user-friendly message')
}

Input Validation

Use Zod for schema-based validation:
import { z } from 'zod'

const schema = z.object({
  email: z.string().email(),
  age: z.number().int().min(0).max(150)
})

const validated = schema.parse(input)

Console.log

  • No console.log statements in production code
  • Use proper logging libraries instead
  • See hooks for automatic detection

Testing

E2E Testing

Use Playwright as the E2E testing framework for critical user flows.
import { test, expect } from '@playwright/test'

test('user can log in', async ({ page }) => {
  await page.goto('/login')
  await page.fill('[name=email]', '[email protected]')
  await page.fill('[name=password]', 'password123')
  await page.click('button[type=submit]')
  await expect(page).toHaveURL('/dashboard')
})

Agent Support

e2e-runner

Playwright E2E testing specialist

Patterns

API Response Format

interface ApiResponse<T> {
  success: boolean
  data?: T
  error?: string
  meta?: {
    total: number
    page: number
    limit: number
  }
}

Custom Hooks Pattern

export function useDebounce<T>(value: T, delay: number): T {
  const [debouncedValue, setDebouncedValue] = useState<T>(value)

  useEffect(() => {
    const handler = setTimeout(() => setDebouncedValue(value), delay)
    return () => clearTimeout(handler)
  }, [value, delay])

  return debouncedValue
}

Repository Pattern

interface Repository<T> {
  findAll(filters?: Filters): Promise<T[]>
  findById(id: string): Promise<T | null>
  create(data: CreateDto): Promise<T>
  update(id: string, data: UpdateDto): Promise<T>
  delete(id: string): Promise<void>
}

Security

Secret Management

const apiKey = "sk-proj-xxxxx"

Agent Support

security-reviewer

Use for comprehensive security audits

Hooks

PostToolUse Hooks

Configure in ~/.claude/settings.json:
Automatically runs Prettier on JavaScript and TypeScript files after edits to maintain consistent formatting.
{
  "matcher": "Edit",
  "hooks": [{
    "type": "command",
    "command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/hooks/post-edit-format.js\""
  }]
}
Runs TypeScript compiler in check mode (tsc --noEmit) to catch type errors immediately.
{
  "matcher": "Edit",
  "hooks": [{
    "type": "command",
    "command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/hooks/post-edit-typecheck.js\""
  }]
}
Detects console.log statements in edited files and warns to use proper logging instead.
{
  "matcher": "Edit",
  "hooks": [{
    "type": "command",
    "command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/hooks/post-edit-console-warn.js\""
  }]
}

Stop Hooks

Final check for any console.log statements that may have been added during the session.
{
  "matcher": "*",
  "hooks": [{
    "type": "command",
    "command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/hooks/check-console-log.js\""
  }]
}

Common Rules

Language-agnostic base rules

Hooks Overview

Complete hook system reference