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 (extracting common patterns)
- 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
- code-duplication.md - Extract common patterns, DRY principle, when to consolidate
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 - Convert conditionals to lookups, hoist invariants, early returns
- reduce-looping.md - Single-pass operations, O(1) lookups, typed arrays
- memoization.md - Hoist invariants, precompute constants, cache expensive operations
- batching.md - Batch I/O operations
- predictable-execution.md - Sequential access, cache locality, grouped data
- bounded-iteration.md - Set limits on loops and queues
- defer-await.md - Move await into branches that need it
- cache-property-access.md - Cache lookups, eliminate aliases, avoid unnecessary destructuring
- cache-storage-api.md - Cache localStorage/sessionStorage/cookie reads
- object-operations.md - Safe mutation, shallow clones, preallocate shapes
- avoid-allocations.md - Inline simple computations, avoid needless variables, reduce GC pressure
- currying.md - Curry to precompute constant parameters, optimize hot paths
- performance-misc.md - Strings, regex, async overhead, closures, try/catch
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
}
Example 5: Avoiding Needless Allocations
Task: "This random number function has GC pressure when called in a loop"
Approach:
- Read AGENTS.md overview
- Identify issue: intermediate variable creating unnecessary allocations
- Load avoid-allocations.md
- Inline simple computation to eliminate allocation
Before:
function randomInt(min: number, max: number): number {
const minCeil = Math.ceil(min);
const maxFloor = Math.floor(max);
const range = maxFloor - minCeil + 1;
return Math.floor(Math.random() * range + minCeil);
}
After:
function randomInt(min: number, max: number): number {
const minCeil = Math.ceil(min);
const maxFloor = Math.floor(max);
return Math.floor(Math.random() * (maxFloor - minCeil + 1) + minCeil);
}
Example 6: Currying for Performance
Task: "This round() function recomputes 10 ** precision on every call in a loop"
Approach:
- Read AGENTS.md overview
- Identify issue: expensive exponentiation repeated with constant parameter
- Load currying.md
- Convert to curried form to precompute multiplier
Before:
export function round(precision: number, value: number): number {
const multiplier = 10 ** precision;
return Math.round(value * multiplier) / multiplier;
}
for (const price of prices) {
rounded.push(round(2, price)); // Recomputes 10 ** 2 every time
}
After:
export function round(precision: number): (value: number) => number;
export function round(precision: number, value: number): number;
export function round(
precision: number,
value?: number,
): number | ((value: number) => number) {
const multiplier = 10 ** precision;
if (value === undefined) {
return (v: number) => Math.round(v * multiplier) / multiplier;
}
return Math.round(value * multiplier) / multiplier;
}
const roundTo2 = round(2); // Compute once
for (const price of prices) {
rounded.push(roundTo2(price)); // Reuse precomputed multiplier
}
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 code needs JSDoc: Functions, types, interfaces, constants, and classes require JSDoc
- Required tags (all code): Description,
@param, @template, @returns
- Required tags (exports only):
@throws, @example (in addition to above)
- 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, avoid needless allocations, currying for hot paths), 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---5
6# JavaScript and TypeScript Best Practices
7
8Comprehensive coding standards and performance optimization guide for JavaScript and TypeScript applications, designed for AI agents and LLMs working with modern JavaScript/TypeScript codebases.
9
10## When to Activate This Skill
11
12Use this skill when the task involves:
13
14### Writing JavaScript/TypeScript Code
15- Creating new functions, classes, or modules
16- Implementing control flow logic (conditionals, loops, early returns)
17- Managing state with variables (`const` vs `let`)
18- Writing TypeScript type definitions, interfaces, or generics
19- Defining enums or constant objects
20- Structuring code with proper naming conventions
21
22### TypeScript-Specific Tasks
23- Fixing type errors or improving type safety
24- Replacing `any` with proper types (`unknown`, generics)
25- Converting `enum` to `as const` objects
26- Choosing between `type` and `interface`
27- Adding type annotations to untyped code
28- Implementing generic functions or utilities
29
30### Code Quality & Style
31- Refactoring nested conditionals to early returns
32- Simplifying complex control flow
33- Improving variable naming (descriptive names, proper prefixes for booleans)
34- Reducing code duplication (extracting common patterns)
35- Applying consistent code style
36- Removing commented-out code or outdated comments
37
38### Safety & Validation
39- Adding input validation at system boundaries
40- Implementing assertions for programmer error detection
41- Improving error handling patterns
42- Writing better error messages (user-facing or developer-facing)
43- Validating external data with schemas (Zod, etc.)
44- Preventing null/undefined propagation
45
46### Performance Optimization
47- Reducing unnecessary branching or conditionals
48- 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 calls
51- Optimizing loops (cache property access, array length)
52- Deferring `await` operations to avoid blocking
53- Caching `localStorage`, `sessionStorage`, or cookie reads
54
55### Documentation
56- Adding JSDoc comments to exported functions
57- Using proper comment markers (TODO, FIXME, HACK, NOTE, PERF)
58- Removing unnecessary comments
59- Preserving important comments (business logic, linter directives)
60- Documenting function parameters, return types, and examples
61
62### Code Review
63- Reviewing code for style violations
64- Identifying performance anti-patterns
65- Checking for safety issues (missing validation, poor error handling)
66- Ensuring TypeScript best practices
67- Verifying proper documentation
68
69## When NOT to Use This Skill
70
71Do not activate for:
72- Framework-specific code (React, Vue, Angular) - use framework-specific skills instead
73- 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-related
75- Testing code (use a testing-specific skill if available)
76- Database queries or ORM usage
77- CSS, HTML, or styling (unless embedded in JS/TS files)
78- Package management (npm, yarn, pnpm)
79
80## How to Use
81
82This skill uses a **progressive disclosure** structure to minimize context usage:
83
84### 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.
86
87### 2. Load Specific Rules as Needed
88When you identify a relevant pattern or issue, load the corresponding reference file for detailed implementation guidance:
89
90**General Best Practices:**
91- [naming-conventions.md](references/naming-conventions.md) - Descriptive names, qualifier ordering, boolean prefixes
92- [functions.md](references/functions.md) - Function size, parameters, explicit values
93- [control-flow.md](references/control-flow.md) - Early returns, flat structure, block style
94- [state-management.md](references/state-management.md) - const vs let, immutability, pure functions
95- [return-values.md](references/return-values.md) - Return zero values instead of null/undefined
96- [misc.md](references/misc.md) - Line endings, defensive programming, technical debt
97- [code-duplication.md](references/code-duplication.md) - Extract common patterns, DRY principle, when to consolidate
98
99**TypeScript:**
100- [any.md](references/any.md) - Avoid any, use unknown or generics
101- [enums.md](references/enums.md) - Use as const objects instead of enum
102- [type-vs-interface.md](references/type-vs-interface.md) - Prefer type over interface
103
104**Safety:**
105- [input-validation.md](references/input-validation.md) - Validate external data with schemas
106- [assertions.md](references/assertions.md) - Split assertions, include values
107- [error-handling.md](references/error-handling.md) - Handle all errors explicitly
108- [error-messages.md](references/error-messages.md) - User-friendly vs developer-specific messages
109
110**Performance:**
111- [reduce-branching.md](references/reduce-branching.md) - Convert conditionals to lookups, hoist invariants, early returns
112- [reduce-looping.md](references/reduce-looping.md) - Single-pass operations, O(1) lookups, typed arrays
113- [memoization.md](references/memoization.md) - Hoist invariants, precompute constants, cache expensive operations
114- [batching.md](references/batching.md) - Batch I/O operations
115- [predictable-execution.md](references/predictable-execution.md) - Sequential access, cache locality, grouped data
116- [bounded-iteration.md](references/bounded-iteration.md) - Set limits on loops and queues
117- [defer-await.md](references/defer-await.md) - Move await into branches that need it
118- [cache-property-access.md](references/cache-property-access.md) - Cache lookups, eliminate aliases, avoid unnecessary destructuring
119- [cache-storage-api.md](references/cache-storage-api.md) - Cache localStorage/sessionStorage/cookie reads
120- [object-operations.md](references/object-operations.md) - Safe mutation, shallow clones, preallocate shapes
121- [avoid-allocations.md](references/avoid-allocations.md) - Inline simple computations, avoid needless variables, reduce GC pressure
122- [currying.md](references/currying.md) - Curry to precompute constant parameters, optimize hot paths
123- [performance-misc.md](references/performance-misc.md) - Strings, regex, async overhead, closures, try/catch
124
125**Documentation:**
126- [jsdoc.md](references/jsdoc.md) - Well-formed JSDoc for exports
127- [comment-markers.md](references/comment-markers.md) - TODO, FIXME, HACK, NOTE markers
128- [comments-to-remove.md](references/comments-to-remove.md) - Commented code, edit history
129- [comments-to-preserve.md](references/comments-to-preserve.md) - Markers, linter directives, business logic
130- [comments-placement.md](references/comments-placement.md) - Move end-of-line comments above code
131
132### 3. Apply the Pattern
133Each reference file contains:
134- ❌ Incorrect examples showing the anti-pattern
135- ✅ Correct examples showing the optimal implementation
136- Explanations of why the pattern matters
137
138## Examples
139
140### Example 1: Optimizing Array Operations
141**Task:** "This filter().map() chain is slow on large arrays"
142
143**Approach:**
1441. Read AGENTS.md overview
1452. Identify issue: multiple iterations over same array
1463. Load [reduce-looping.md](references/reduce-looping.md)
1474. Replace chained methods with single reduce() call
148
149**Before:**
150```ts
151const result = items.filter(x => x.active).map(x => x.id);
152```
153
154**After:**
155```ts
156const result = items.reduce((acc, x) =>
157 x.active ? [...acc, x.id] : acc,
158 []
159);
160```
161
162### Example 2: Fixing TypeScript `any` Usage
163**Task:** "Replace `any` types with proper TypeScript types"
164
165**Approach:**
1661. Read AGENTS.md overview
1672. Identify need for type safety
1683. Load [any.md](references/any.md)
1694. Replace `any` with `unknown` or generics based on use case
170
171**Before:**
172```ts
173function process(data: any): any { /**/ }
174```
175
176**After:**
177```ts
178function process<T>(data: T): Result<T> { /**/ }
179// or
180function process(data: unknown): User { /**/ }
181```
182
183### Example 3: Improving Error Messages
184**Task:** "Make error messages more helpful for users"
185
186**Approach:**
1871. Read AGENTS.md overview
1882. Identify need for better error messaging
1893. Load [error-messages.md](references/error-messages.md)
1904. Replace technical errors with user-friendly, actionable messages
191
192**Before:**
193```ts
194throw new Error('500');
195```
196
197**After:**
198```ts
199alert(
200 'We're having trouble connecting to our server.\n' +
201 'Please check your internet connection and try again.'
202);
203```
204
205### Example 4: Caching Storage API Calls
206**Task:** "This function calls localStorage.getItem() 100 times in a loop"
207
208**Approach:**
2091. Read AGENTS.md overview
2102. Identify performance issue: repeated storage reads
2113. Load [cache-storage-api.md](references/cache-storage-api.md)
2124. Implement Map-based cache with invalidation strategy
213
214**Before:**
215```ts
216for (const item of items) {
217 const theme = localStorage.getItem('theme');
218 // ... 100 storage reads
219}
220```
221
222**After:**
223```ts
224const storageCache = new Map();
225function getCached(key) {
226 if (!storageCache.has(key)) {
227 storageCache.set(key, localStorage.getItem(key));
228 }
229 return storageCache.get(key);
230}
231
232for (const item of items) {
233 const theme = getCached('theme');
234 // ... 1 storage read
235}
236```
237
238### Example 5: Avoiding Needless Allocations
239**Task:** "This random number function has GC pressure when called in a loop"
240
241**Approach:**
2421. Read AGENTS.md overview
2432. Identify issue: intermediate variable creating unnecessary allocations
2443. Load [avoid-allocations.md](references/avoid-allocations.md)
2454. Inline simple computation to eliminate allocation
246
247**Before:**
248```ts
249function randomInt(min: number, max: number): number {
250 const minCeil = Math.ceil(min);
251 const maxFloor = Math.floor(max);
252 const range = maxFloor - minCeil + 1;
253 return Math.floor(Math.random() * range + minCeil);
254}
255```
256
257**After:**
258```ts
259function randomInt(min: number, max: number): number {
260 const minCeil = Math.ceil(min);
261 const maxFloor = Math.floor(max);
262 return Math.floor(Math.random() * (maxFloor - minCeil + 1) + minCeil);
263}
264```
265
266### Example 6: Currying for Performance
267**Task:** "This round() function recomputes 10 ** precision on every call in a loop"
268
269**Approach:**
2701. Read AGENTS.md overview
2712. Identify issue: expensive exponentiation repeated with constant parameter
2723. Load [currying.md](references/currying.md)
2734. Convert to curried form to precompute multiplier
274
275**Before:**
276```ts
277export function round(precision: number, value: number): number {
278 const multiplier = 10 ** precision;
279 return Math.round(value * multiplier) / multiplier;
280}
281
282for (const price of prices) {
283 rounded.push(round(2, price)); // Recomputes 10 ** 2 every time
284}
285```
286
287**After:**
288```ts
289export function round(precision: number): (value: number) => number;
290export function round(precision: number, value: number): number;
291export function round(
292 precision: number,
293 value?: number,
294): number | ((value: number) => number) {
295 const multiplier = 10 ** precision;
296
297 if (value === undefined) {
298 return (v: number) => Math.round(v * multiplier) / multiplier;
299 }
300
301 return Math.round(value * multiplier) / multiplier;
302}
303
304const roundTo2 = round(2); // Compute once
305for (const price of prices) {
306 rounded.push(roundTo2(price)); // Reuse precomputed multiplier
307}
308```
309
310## Important Notes
311
312### Performance Philosophy
313Design for performance from the start. Optimize slowest resources first:
314```
315network >> disk >> memory >> cpu
316```
317
318Always **benchmark your assumptions** before moving on. Premature optimization of CPU-bound operations while ignoring network bottlenecks wastes time.
319
320### State Management Principles
321- **Prefer `const`**: Use `let` only for valid performance reasons
322- **Immutability**: Never mutate passed references; create copies
323- **Pure functions**: Keep leaf functions pure; centralize state in parents
324- **Zero values**: Return `[]`, `{}`, `0`, `''` instead of `null`/`undefined`
325
326### TypeScript Best Practices
327- **Avoid `any`**: Use `unknown` for truly unknown types, generics for flexibility
328- **Avoid `enum`**: Use `as const` objects for better tree-shaking and type inference
329- **Prefer `type`**: Use `interface` only for declaration merging or class contracts
330
331### Code Quality Principles
332- **Functions under 50 lines**: Break down large functions
333- **Early returns**: Prefer flat control flow over nested conditionals
334- **Descriptive names**: Use complete words, append qualifiers in descending order
335- **Explicit values**: Avoid default parameters; make all values explicit at call site
336
337### Safety First
338- **Validate at boundaries**: All external data must be validated (user input, API responses)
339- **Assertions for programmer errors**: Crash on corrupted code state
340- **Split compound assertions**: One assertion per invariant
341- **Include values in messages**: Always show actual vs expected values
342
343### Documentation Standards
344- **All code needs JSDoc**: Functions, types, interfaces, constants, and classes require JSDoc
345- **Required tags (all code)**: Description, `@param`, `@template`, `@returns`
346- **Required tags (exports only)**: `@throws`, `@example` (in addition to above)
347- **Use comment markers**: TODO, FIXME, HACK, NOTE, REVIEW, PERF
348- **Remove dead code**: No commented-out code or edit history
349- **Preserve business logic**: Keep comments explaining "why", not "what"
350
351## Optimization Strategies
352
353When optimizing performance:
354
3551. **Measure first**: Use profiling tools to identify actual bottlenecks
3562. **Network first**: Optimize network requests before code execution
3573. **Reduce iterations**: Single reduce() instead of chained filter().map()
3584. **Cache lookups**: Use Set for O(1) membership checks, cache property access in loops
3595. **Defer work**: Move expensive operations (await, computation) into branches that need them
3606. **Batch operations**: Group I/O operations to reduce overhead
3617. **Predictable paths**: Write code with clear execution flow for CPU optimization
362
363## Additional Context
364
365### When Functions Are Too Small
366Some patterns (like lookup tables) may seem to violate the "no premature optimization" principle. These are **architectural choices**, not optimizations:
367- Lookup tables improve maintainability (add entries without new conditionals)
368- Early returns reduce cognitive load (fewer nested levels)
369- Const over let prevents accidental mutations (correctness, not speed)
370
371### Defensive Programming
372This skill emphasizes "negative-space" or defensive programming:
373- Return zero values to eliminate downstream null checks
374- Assert invariants to catch bugs early
375- Validate at boundaries to contain invalid data
376- Handle all errors explicitly (no silent failures)
377
378The goal is **correctness first, performance second**.