Code Verification Skill
Comprehensive code verification against project standards, type safety, performance, and best practices.
Quick Start
bash
# Run all verification checks npm run lint && npm run typecheck && npm run test # Or use a combined script npm run verify
Skill Contents
Documentation
- •
docs/typescript-safety.md- TypeScript best practices - •
docs/memory-leaks.md- Memory leak prevention
Examples
- •
examples/cleanup-patterns.ts- Proper cleanup examples - •
examples/type-guards.ts- Type narrowing patterns
Templates
- •
templates/pr-checklist.md- PR review checklist
Reference
- •
REFERENCE.md- Quick reference cheatsheet
Verification Categories
1. Type Safety (TypeScript)
No Implicit Any
typescript
// ❌ BAD: Implicit any
function processData(data) {
return data.map((item) => item.name);
}
// ✅ GOOD: Explicit types
function processData(data: User[]): string[] {
return data.map((item) => item.name);
}
Proper Null Handling
typescript
// ❌ BAD: Missing null check
function getUsername(user: User | null): string {
return user.name; // Error: user might be null
}
// ✅ GOOD: Null handling
function getUsername(user: User | null): string {
return user?.name ?? 'Anonymous';
}
// ✅ ALSO GOOD: Early return
function getUsername(user: User | null): string {
if (!user) return 'Anonymous';
return user.name;
}
Generic Type Usage
typescript
// ❌ BAD: Overly generic
function fetch<T>(url: string): Promise<T> {
return fetch(url).then((r) => r.json());
}
// ✅ GOOD: Constrained generics
function fetchData<T extends Record<string, unknown>>(
url: string,
schema: z.ZodSchema<T>,
): Promise<T> {
return fetch(url)
.then((r) => r.json())
.then((data) => schema.parse(data));
}
2. Memory Leak Prevention
Event Listener Cleanup
typescript
// ❌ BAD: No cleanup
useEffect(() => {
window.addEventListener('resize', handleResize);
}, []);
// ✅ GOOD: With cleanup
useEffect(() => {
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
Subscription Cleanup
typescript
// ❌ BAD: Uncleaned subscription
useEffect(() => {
const subscription = observable.subscribe(handler);
}, []);
// ✅ GOOD: With cleanup
useEffect(() => {
const subscription = observable.subscribe(handler);
return () => subscription.unsubscribe();
}, []);
AbortController for Fetch
typescript
// ❌ BAD: No cancellation
useEffect(() => {
fetch('/api/data')
.then((r) => r.json())
.then(setData);
}, []);
// ✅ GOOD: With abort
useEffect(() => {
const controller = new AbortController();
fetch('/api/data', { signal: controller.signal })
.then((r) => r.json())
.then(setData)
.catch((e) => {
if (e.name !== 'AbortError') throw e;
});
return () => controller.abort();
}, []);
Timer Cleanup
typescript
// ❌ BAD: No cleanup
useEffect(() => {
setInterval(() => tick(), 1000);
}, []);
// ✅ GOOD: With cleanup
useEffect(() => {
const id = setInterval(() => tick(), 1000);
return () => clearInterval(id);
}, []);
3. React Best Practices
Dependency Arrays
typescript
// ❌ BAD: Missing dependency
useEffect(() => {
fetchUser(userId);
}, []); // userId missing!
// ✅ GOOD: Complete dependencies
useEffect(() => {
fetchUser(userId);
}, [userId]);
// ✅ GOOD: Stable callback reference
const fetchUserCallback = useCallback(() => {
fetchUser(userId);
}, [userId]);
Proper Key Usage
typescript
// ❌ BAD: Index as key (unstable)
{items.map((item, index) => (
<Item key={index} data={item} />
))}
// ✅ GOOD: Unique, stable key
{items.map(item => (
<Item key={item.id} data={item} />
))}
Memoization
typescript
// ❌ BAD: Unnecessary re-renders
const ExpensiveList = ({ items, onSelect }) => {
const sorted = items.sort((a, b) => a.name.localeCompare(b.name));
return sorted.map(item => <Item key={item.id} {...item} />);
};
// ✅ GOOD: Memoized computation
const ExpensiveList = ({ items, onSelect }) => {
const sorted = useMemo(
() => [...items].sort((a, b) => a.name.localeCompare(b.name)),
[items]
);
return sorted.map(item => <Item key={item.id} {...item} />);
};
4. Coding Patterns
Early Returns
typescript
// ❌ BAD: Deeply nested
function processUser(user: User | null) {
if (user) {
if (user.isActive) {
if (user.hasPermission) {
return performAction(user);
}
}
}
return null;
}
// ✅ GOOD: Guard clauses
function processUser(user: User | null) {
if (!user) return null;
if (!user.isActive) return null;
if (!user.hasPermission) return null;
return performAction(user);
}
Single Responsibility
typescript
// ❌ BAD: Does too much
function handleSubmit(formData: FormData) {
// Validates
// Transforms
// Makes API call
// Updates state
// Shows notification
// Logs analytics
}
// ✅ GOOD: Single responsibility
function handleSubmit(formData: FormData) {
const validated = validateFormData(formData);
const transformed = transformForAPI(validated);
return submitToAPI(transformed);
}
Descriptive Naming
typescript
// ❌ BAD: Unclear names
const d = new Date();
const x = users.filter((u) => u.a);
const fn = () => {
/* ... */
};
// ✅ GOOD: Descriptive names
const createdAt = new Date();
const activeUsers = users.filter((user) => user.isActive);
const handleFormSubmit = () => {
/* ... */
};
5. Error Handling
Error Boundaries
typescript
// ✅ GOOD: Error boundary for fallible code
<ErrorBoundary fallback={<ErrorFallback />}>
<FeatureComponent />
</ErrorBoundary>
Explicit Error Handling
typescript
// ❌ BAD: Swallowed error
try {
await riskyOperation();
} catch {
// Silent failure
}
// ✅ GOOD: Explicit handling
try {
await riskyOperation();
} catch (error) {
console.error('Operation failed:', error);
showErrorNotification('Something went wrong');
reportToErrorTracker(error);
}
6. Performance
Avoid Layout Thrashing
typescript
// ❌ BAD: Forces multiple reflows
elements.forEach((el) => {
const width = el.offsetWidth; // Read
el.style.width = width + 10 + 'px'; // Write
});
// ✅ GOOD: Batch reads and writes
const widths = elements.map((el) => el.offsetWidth); // All reads
elements.forEach((el, i) => {
el.style.width = widths[i] + 10 + 'px'; // All writes
});
Lazy Loading
typescript
// ✅ GOOD: Lazy load heavy components
const HeavyChart = lazy(() => import('./HeavyChart'));
function Dashboard() {
return (
<Suspense fallback={<ChartSkeleton />}>
<HeavyChart />
</Suspense>
);
}
Verification Checklist
markdown
### Type Safety - [ ] No implicit `any` types - [ ] No `@ts-ignore` without justification - [ ] Proper null/undefined handling - [ ] Generic types used where appropriate - [ ] No type assertions without validation ### Memory & Resources - [ ] Event listeners cleaned up - [ ] Subscriptions unsubscribed - [ ] Timers cleared - [ ] Fetch requests cancellable - [ ] No circular references ### React Patterns - [ ] useEffect dependencies complete - [ ] useMemo/useCallback used appropriately - [ ] Keys are stable and unique - [ ] Error boundaries for fallible code - [ ] No state updates on unmounted components ### Code Quality - [ ] Early return pattern used - [ ] Single responsibility principle - [ ] Descriptive naming - [ ] No magic numbers/strings - [ ] Comments explain "why", not "what" ### Error Handling - [ ] Errors caught and handled - [ ] User-friendly error messages - [ ] Errors logged appropriately - [ ] Recovery paths defined ### Performance - [ ] No unnecessary re-renders - [ ] Heavy computations memoized - [ ] Lazy loading for large components - [ ] No layout thrashing - [ ] Images optimized
Automated Verification
ESLint Rules
json
{
"rules": {
"@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/no-unused-vars": "error",
"@typescript-eslint/strict-boolean-expressions": "warn",
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn",
"no-console": ["warn", { "allow": ["warn", "error"] }]
}
}
TypeScript Config
json
{
"compilerOptions": {
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"noUncheckedIndexedAccess": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
}
}
Commands
bash
# Type checking npm run typecheck # Linting npm run lint npm run lint:fix # All tests npm run test # Combined verification npm run verify # Find unused exports npx ts-prune # Analyze bundle size npx vite-bundle-visualizer
PR Review Template
markdown
## Code Review: [PR Title] ### Verification Status | Check | Status | Notes | | -------------- | ------ | ----- | | Type Safety | ✅/❌ | | | Memory Leaks | ✅/❌ | | | React Patterns | ✅/❌ | | | Error Handling | ✅/❌ | | | Tests | ✅/❌ | | | Performance | ✅/❌ | | ### Issues Found - [ ] Issue 1: Description - [ ] Issue 2: Description ### Suggestions 1. Consider... 2. Could improve... ### Approved: Yes/No
After Verification
[!IMPORTANT] After verifying code, you MUST:
- •Run all verification commands
- •Fix ALL errors and warnings found
- •Ensure no regressions introduced
- •Document any exceptions
- •Update tests if behavior changed