JavaScript and TypeScript Best Practices
Comprehensive coding standards and performance optimization guide for JavaScript and TypeScript applications, designed for AI agents and LLMs working with modern JavaScript/TypeScript codebases.
When to Activate This Skill
Use this skill when the task involves:
Writing JavaScript/TypeScript Code
- Creating new functions, classes, or modules
- Implementing control flow logic (conditionals, loops, early returns)
- Managing state with variables (
const vs let)
- Writing TypeScript type definitions, interfaces, or generics
- Defining enums or constant objects
- Structuring code with proper naming conventions
TypeScript-Specific Tasks
- Fixing type errors or improving type safety
- Replacing
any with proper types (unknown, generics)
- Converting
enum to as const objects
- Choosing between
type and interface
- Adding type annotations to untyped code
- Implementing generic functions or utilities
Code Quality & Style
- Refactoring nested conditionals to early returns
- Simplifying complex control flow
- Improving variable naming (descriptive names, proper prefixes for booleans)
- Reducing code duplication
- Applying consistent code style
- Removing commented-out code or outdated comments
Safety & Validation
- Adding input validation at system boundaries
- Implementing assertions for programmer error detection
- Improving error handling patterns
- Writing better error messages (user-facing or developer-facing)
- Validating external data with schemas (Zod, etc.)
- Preventing null/undefined propagation
Performance Optimization
- Reducing unnecessary branching or conditionals
- Optimizing array operations (reduce instead of chained filter/map)
- Implementing efficient data structures (Set vs Array for lookups)
- Caching expensive computations or API calls
- Optimizing loops (cache property access, array length)
- Deferring
await operations to avoid blocking
- Caching
localStorage, sessionStorage, or cookie reads
Documentation
- Adding JSDoc comments to exported functions
- Using proper comment markers (TODO, FIXME, HACK, NOTE, PERF)
- Removing unnecessary comments
- Preserving important comments (business logic, linter directives)
- Documenting function parameters, return types, and examples
Code Review
- Reviewing code for style violations
- Identifying performance anti-patterns
- Checking for safety issues (missing validation, poor error handling)
- Ensuring TypeScript best practices
- Verifying proper documentation
When NOT to Use This Skill
Do not activate for:
- Framework-specific code (React, Vue, Angular) - use framework-specific skills instead
- Node.js-specific APIs or server-side concerns (unless general JS/TS patterns apply)
- Build tooling configuration (webpack, vite, tsconfig.json) unless code quality-related
- Testing code (use a testing-specific skill if available)
- Database queries or ORM usage
- CSS, HTML, or styling (unless embedded in JS/TS files)
- Package management (npm, yarn, pnpm)
How to Use
This skill uses a progressive disclosure structure to minimize context usage:
1. Start with the Overview (AGENTS.md)
Read AGENTS.md for a concise overview of all rules with one-line summaries organized by category.
2. Load Specific Rules as Needed
When you identify a relevant pattern or issue, load the corresponding reference file for detailed implementation guidance:
General Best Practices:
- naming-conventions.md - Descriptive names, qualifier ordering, boolean prefixes
- functions.md - Function size, parameters, explicit values
- control-flow.md - Early returns, flat structure, block style
- state-management.md - const vs let, immutability, pure functions
- return-values.md - Return zero values instead of null/undefined
- misc.md - Line endings, defensive programming, technical debt
TypeScript:
- any.md - Avoid any, use unknown or generics
- enums.md - Use as const objects instead of enum
- type-vs-interface.md - Prefer type over interface
Safety:
- input-validation.md - Validate external data with schemas
- assertions.md - Split assertions, include values
- error-handling.md - Handle all errors explicitly
- error-messages.md - User-friendly vs developer-specific messages
Performance:
- reduce-branching.md - Use lookup tables instead of conditionals
- reduce-looping.md - reduce vs chained methods, Set.has() vs Array.includes()
- memoization.md - When to memoize (avoid trivial computations)
- batching.md - Batch I/O operations
- predictable-execution.md - Clear execution paths for CPU caching
- bounded-iteration.md - Set limits on loops and queues
- defer-await.md - Move await into branches that need it
- cache-property-access.md - Cache object lookups in loops
- cache-storage-api.md - Cache localStorage/sessionStorage/cookie reads
Documentation:
- jsdoc.md - Well-formed JSDoc for exports
- comment-markers.md - TODO, FIXME, HACK, NOTE markers
- comments-to-remove.md - Commented code, edit history
- comments-to-preserve.md - Markers, linter directives, business logic
- comments-placement.md - Move end-of-line comments above code
3. Apply the Pattern
Each reference file contains:
- ❌ Incorrect examples showing the anti-pattern
- ✅ Correct examples showing the optimal implementation
- Explanations of why the pattern matters
Examples
Example 1: Optimizing Array Operations
Task: "This filter().map() chain is slow on large arrays"
Approach:
- Read AGENTS.md overview
- Identify issue: multiple iterations over same array
- Load reduce-looping.md
- Replace chained methods with single reduce() call
Before:
const result = items.filter(x => x.active).map(x => x.id);
After:
const result = items.reduce((acc, x) =>
x.active ? [...acc, x.id] : acc,
[]
);
Example 2: Fixing TypeScript any Usage
Task: "Replace any types with proper TypeScript types"
Approach:
- Read AGENTS.md overview
- Identify need for type safety
- Load any.md
- Replace
any with unknown or generics based on use case
Before:
function process(data: any): any { /**/ }
After:
function process<T>(data: T): Result<T> { /**/ }
// or
function process(data: unknown): User { /**/ }
Example 3: Improving Error Messages
Task: "Make error messages more helpful for users"
Approach:
- Read AGENTS.md overview
- Identify need for better error messaging
- Load error-messages.md
- Replace technical errors with user-friendly, actionable messages
Before:
throw new Error('500');
After:
alert(
'We're having trouble connecting to our server.\n' +
'Please check your internet connection and try again.'
);
Example 4: Caching Storage API Calls
Task: "This function calls localStorage.getItem() 100 times in a loop"
Approach:
- Read AGENTS.md overview
- Identify performance issue: repeated storage reads
- Load cache-storage-api.md
- Implement Map-based cache with invalidation strategy
Before:
for (const item of items) {
const theme = localStorage.getItem('theme');
// ... 100 storage reads
}
After:
const storageCache = new Map();
function getCached(key) {
if (!storageCache.has(key)) {
storageCache.set(key, localStorage.getItem(key));
}
return storageCache.get(key);
}
for (const item of items) {
const theme = getCached('theme');
// ... 1 storage read
}
Important Notes
Performance Philosophy
Design for performance from the start. Optimize slowest resources first:
network >> disk >> memory >> cpu
Always benchmark your assumptions before moving on. Premature optimization of CPU-bound operations while ignoring network bottlenecks wastes time.
State Management Principles
- Prefer
const: Use let only for valid performance reasons
- Immutability: Never mutate passed references; create copies
- Pure functions: Keep leaf functions pure; centralize state in parents
- Zero values: Return
[], {}, 0, '' instead of null/undefined
TypeScript Best Practices
- Avoid
any: Use unknown for truly unknown types, generics for flexibility
- Avoid
enum: Use as const objects for better tree-shaking and type inference
- Prefer
type: Use interface only for declaration merging or class contracts
Code Quality Principles
- Functions under 50 lines: Break down large functions
- Early returns: Prefer flat control flow over nested conditionals
- Descriptive names: Use complete words, append qualifiers in descending order
- Explicit values: Avoid default parameters; make all values explicit at call site
Safety First
- Validate at boundaries: All external data must be validated (user input, API responses)
- Assertions for programmer errors: Crash on corrupted code state
- Split compound assertions: One assertion per invariant
- Include values in messages: Always show actual vs expected values
Documentation Standards
- All exports need JSDoc: Minimum
@param, @returns, @example
- Use comment markers: TODO, FIXME, HACK, NOTE, REVIEW, PERF
- Remove dead code: No commented-out code or edit history
- Preserve business logic: Keep comments explaining "why", not "what"
Optimization Strategies
When optimizing performance:
- Measure first: Use profiling tools to identify actual bottlenecks
- Network first: Optimize network requests before code execution
- Reduce iterations: Single reduce() instead of chained filter().map()
- Cache lookups: Use Set for O(1) membership checks, cache property access in loops
- Defer work: Move expensive operations (await, computation) into branches that need them
- Batch operations: Group I/O operations to reduce overhead
- Predictable paths: Write code with clear execution flow for CPU optimization
Additional Context
When Functions Are Too Small
Some patterns (like lookup tables) may seem to violate the "no premature optimization" principle. These are architectural choices, not optimizations:
- Lookup tables improve maintainability (add entries without new conditionals)
- Early returns reduce cognitive load (fewer nested levels)
- Const over let prevents accidental mutations (correctness, not speed)
Defensive Programming
This skill emphasizes "negative-space" or defensive programming:
- Return zero values to eliminate downstream null checks
- Assert invariants to catch bugs early
- Validate at boundaries to contain invalid data
- Handle all errors explicitly (no silent failures)
The goal is correctness first, performance second.
1---2name: js-ts-best-practices3description: JavaScript and TypeScript best practices covering naming conventions, control flow, state management, TypeScript patterns (avoid any/enum, prefer type over interface), safety (input validation, assertions, error handling), performance optimization (reduce branching/looping, memoization, defer await, cache property access, storage API caching), and documentation (JSDoc, comment markers). Use when writing JS/TS functions, refactoring code for performance, reviewing code quality, fixing type errors, optimizing loops or conditionals, adding validation, or improving error messages.4---56# JavaScript and TypeScript Best Practices78Comprehensive coding standards and performance optimization guide for JavaScript and TypeScript applications, designed for AI agents and LLMs working with modern JavaScript/TypeScript codebases.910## When to Activate This Skill1112Use this skill when the task involves:1314### Writing JavaScript/TypeScript Code15- Creating new functions, classes, or modules16- Implementing control flow logic (conditionals, loops, early returns)17- Managing state with variables (`const` vs `let`)18- Writing TypeScript type definitions, interfaces, or generics19- Defining enums or constant objects20- Structuring code with proper naming conventions2122### TypeScript-Specific Tasks23- Fixing type errors or improving type safety24- Replacing `any` with proper types (`unknown`, generics)25- Converting `enum` to `as const` objects26- Choosing between `type` and `interface`27- Adding type annotations to untyped code28- Implementing generic functions or utilities2930### Code Quality & Style31- Refactoring nested conditionals to early returns32- Simplifying complex control flow33- Improving variable naming (descriptive names, proper prefixes for booleans)34- Reducing code duplication35- Applying consistent code style36- Removing commented-out code or outdated comments3738### Safety & Validation39- Adding input validation at system boundaries40- Implementing assertions for programmer error detection41- Improving error handling patterns42- Writing better error messages (user-facing or developer-facing)43- Validating external data with schemas (Zod, etc.)44- Preventing null/undefined propagation4546### Performance Optimization47- Reducing unnecessary branching or conditionals48- Optimizing array operations (reduce instead of chained filter/map)49- Implementing efficient data structures (Set vs Array for lookups)50- Caching expensive computations or API calls51- Optimizing loops (cache property access, array length)52- Deferring `await` operations to avoid blocking53- Caching `localStorage`, `sessionStorage`, or cookie reads5455### Documentation56- Adding JSDoc comments to exported functions57- Using proper comment markers (TODO, FIXME, HACK, NOTE, PERF)58- Removing unnecessary comments59- Preserving important comments (business logic, linter directives)60- Documenting function parameters, return types, and examples6162### Code Review63- Reviewing code for style violations64- Identifying performance anti-patterns65- Checking for safety issues (missing validation, poor error handling)66- Ensuring TypeScript best practices67- Verifying proper documentation6869## When NOT to Use This Skill7071Do not activate for:72- Framework-specific code (React, Vue, Angular) - use framework-specific skills instead73- Node.js-specific APIs or server-side concerns (unless general JS/TS patterns apply)74- Build tooling configuration (webpack, vite, tsconfig.json) unless code quality-related75- Testing code (use a testing-specific skill if available)76- Database queries or ORM usage77- CSS, HTML, or styling (unless embedded in JS/TS files)78- Package management (npm, yarn, pnpm)7980## How to Use8182This skill uses a **progressive disclosure** structure to minimize context usage:8384### 1. Start with the Overview (AGENTS.md)85Read [AGENTS.md](AGENTS.md) for a concise overview of all rules with one-line summaries organized by category.8687### 2. Load Specific Rules as Needed88When you identify a relevant pattern or issue, load the corresponding reference file for detailed implementation guidance:8990**General Best Practices:**91- [naming-conventions.md](references/naming-conventions.md) - Descriptive names, qualifier ordering, boolean prefixes92- [functions.md](references/functions.md) - Function size, parameters, explicit values93- [control-flow.md](references/control-flow.md) - Early returns, flat structure, block style94- [state-management.md](references/state-management.md) - const vs let, immutability, pure functions95- [return-values.md](references/return-values.md) - Return zero values instead of null/undefined96- [misc.md](references/misc.md) - Line endings, defensive programming, technical debt9798**TypeScript:**99- [any.md](references/any.md) - Avoid any, use unknown or generics100- [enums.md](references/enums.md) - Use as const objects instead of enum101- [type-vs-interface.md](references/type-vs-interface.md) - Prefer type over interface102103**Safety:**104- [input-validation.md](references/input-validation.md) - Validate external data with schemas105- [assertions.md](references/assertions.md) - Split assertions, include values106- [error-handling.md](references/error-handling.md) - Handle all errors explicitly107- [error-messages.md](references/error-messages.md) - User-friendly vs developer-specific messages108109**Performance:**110- [reduce-branching.md](references/reduce-branching.md) - Use lookup tables instead of conditionals111- [reduce-looping.md](references/reduce-looping.md) - reduce vs chained methods, Set.has() vs Array.includes()112- [memoization.md](references/memoization.md) - When to memoize (avoid trivial computations)113- [batching.md](references/batching.md) - Batch I/O operations114- [predictable-execution.md](references/predictable-execution.md) - Clear execution paths for CPU caching115- [bounded-iteration.md](references/bounded-iteration.md) - Set limits on loops and queues116- [defer-await.md](references/defer-await.md) - Move await into branches that need it117- [cache-property-access.md](references/cache-property-access.md) - Cache object lookups in loops118- [cache-storage-api.md](references/cache-storage-api.md) - Cache localStorage/sessionStorage/cookie reads119120**Documentation:**121- [jsdoc.md](references/jsdoc.md) - Well-formed JSDoc for exports122- [comment-markers.md](references/comment-markers.md) - TODO, FIXME, HACK, NOTE markers123- [comments-to-remove.md](references/comments-to-remove.md) - Commented code, edit history124- [comments-to-preserve.md](references/comments-to-preserve.md) - Markers, linter directives, business logic125- [comments-placement.md](references/comments-placement.md) - Move end-of-line comments above code126127### 3. Apply the Pattern128Each reference file contains:129- ❌ Incorrect examples showing the anti-pattern130- ✅ Correct examples showing the optimal implementation131- Explanations of why the pattern matters132133## Examples134135### Example 1: Optimizing Array Operations136**Task:** "This filter().map() chain is slow on large arrays"137138**Approach:**1391. Read AGENTS.md overview1402. Identify issue: multiple iterations over same array1413. Load [reduce-looping.md](references/reduce-looping.md)1424. Replace chained methods with single reduce() call143144**Before:**145```ts146const result = items.filter(x => x.active).map(x => x.id);147```148149**After:**150```ts151const result = items.reduce((acc, x) =>152 x.active ? [...acc, x.id] : acc,153 []154);155```156157### Example 2: Fixing TypeScript `any` Usage158**Task:** "Replace `any` types with proper TypeScript types"159160**Approach:**1611. Read AGENTS.md overview1622. Identify need for type safety1633. Load [any.md](references/any.md)1644. Replace `any` with `unknown` or generics based on use case165166**Before:**167```ts168function process(data: any): any { /**/ }169```170171**After:**172```ts173function process<T>(data: T): Result<T> { /**/ }174// or175function process(data: unknown): User { /**/ }176```177178### Example 3: Improving Error Messages179**Task:** "Make error messages more helpful for users"180181**Approach:**1821. Read AGENTS.md overview1832. Identify need for better error messaging1843. Load [error-messages.md](references/error-messages.md)1854. Replace technical errors with user-friendly, actionable messages186187**Before:**188```ts189throw new Error('500');190```191192**After:**193```ts194alert(195 'We're having trouble connecting to our server.\n' +196 'Please check your internet connection and try again.'197);198```199200### Example 4: Caching Storage API Calls201**Task:** "This function calls localStorage.getItem() 100 times in a loop"202203**Approach:**2041. Read AGENTS.md overview2052. Identify performance issue: repeated storage reads2063. Load [cache-storage-api.md](references/cache-storage-api.md)2074. Implement Map-based cache with invalidation strategy208209**Before:**210```ts211for (const item of items) {212 const theme = localStorage.getItem('theme');213 // ... 100 storage reads214}215```216217**After:**218```ts219const storageCache = new Map();220function getCached(key) {221 if (!storageCache.has(key)) {222 storageCache.set(key, localStorage.getItem(key));223 }224 return storageCache.get(key);225}226227for (const item of items) {228 const theme = getCached('theme');229 // ... 1 storage read230}231```232233## Important Notes234235### Performance Philosophy236Design for performance from the start. Optimize slowest resources first:237```238network >> disk >> memory >> cpu239```240241Always **benchmark your assumptions** before moving on. Premature optimization of CPU-bound operations while ignoring network bottlenecks wastes time.242243### State Management Principles244- **Prefer `const`**: Use `let` only for valid performance reasons245- **Immutability**: Never mutate passed references; create copies246- **Pure functions**: Keep leaf functions pure; centralize state in parents247- **Zero values**: Return `[]`, `{}`, `0`, `''` instead of `null`/`undefined`248249### TypeScript Best Practices250- **Avoid `any`**: Use `unknown` for truly unknown types, generics for flexibility251- **Avoid `enum`**: Use `as const` objects for better tree-shaking and type inference252- **Prefer `type`**: Use `interface` only for declaration merging or class contracts253254### Code Quality Principles255- **Functions under 50 lines**: Break down large functions256- **Early returns**: Prefer flat control flow over nested conditionals257- **Descriptive names**: Use complete words, append qualifiers in descending order258- **Explicit values**: Avoid default parameters; make all values explicit at call site259260### Safety First261- **Validate at boundaries**: All external data must be validated (user input, API responses)262- **Assertions for programmer errors**: Crash on corrupted code state263- **Split compound assertions**: One assertion per invariant264- **Include values in messages**: Always show actual vs expected values265266### Documentation Standards267- **All exports need JSDoc**: Minimum `@param`, `@returns`, `@example`268- **Use comment markers**: TODO, FIXME, HACK, NOTE, REVIEW, PERF269- **Remove dead code**: No commented-out code or edit history270- **Preserve business logic**: Keep comments explaining "why", not "what"271272## Optimization Strategies273274When optimizing performance:2752761. **Measure first**: Use profiling tools to identify actual bottlenecks2772. **Network first**: Optimize network requests before code execution2783. **Reduce iterations**: Single reduce() instead of chained filter().map()2794. **Cache lookups**: Use Set for O(1) membership checks, cache property access in loops2805. **Defer work**: Move expensive operations (await, computation) into branches that need them2816. **Batch operations**: Group I/O operations to reduce overhead2827. **Predictable paths**: Write code with clear execution flow for CPU optimization283284## Additional Context285286### When Functions Are Too Small287Some patterns (like lookup tables) may seem to violate the "no premature optimization" principle. These are **architectural choices**, not optimizations:288- Lookup tables improve maintainability (add entries without new conditionals)289- Early returns reduce cognitive load (fewer nested levels)290- Const over let prevents accidental mutations (correctness, not speed)291292### Defensive Programming293This skill emphasizes "negative-space" or defensive programming:294- Return zero values to eliminate downstream null checks295- Assert invariants to catch bugs early296- Validate at boundaries to contain invalid data297- Handle all errors explicitly (no silent failures)298299The goal is **correctness first, performance second**.