Date: 2026-03-19
Files Audited: 137 TypeScript files
Audit Type: Static Analysis
Files Affected: 30+ files in src/foliage/, src/compute/, src/rendering/
Issue: Cannot find module 'three/tsl' or 'three/webgpu'
error TS2307: Cannot find module 'three/tsl' or its corresponding type declarations.
error TS2307: Cannot find module 'three/webgpu' or its corresponding type declarations.
Root Cause: TypeScript moduleResolution setting doesn't support three/tsl path aliases.
Fix: Update tsconfig.json:
{
"compilerOptions": {
"moduleResolution": "bundler"
}
}File: src/foliage/common.ts:1052
Issue: Variable used but never declared
_scratchVec1.set(0, 0, 0); // _scratchVec1 doesn't existFix: Add declaration or use existing scratch variable:
const _scratchVec1 = new THREE.Vector3();File: src/foliage/common.ts:954
Issue: Expected 1-2 arguments, but got 0
// Line 954 - likely a geometry constructor missing parameters
new THREE.SphereGeometry(); // Needs radius, widthSegments, etc.File: src/foliage/dandelion-seeds.ts:193-195
Issue: Property 'updateRange' doesn't exist on type 'InstancedBufferAttribute'
this.attribute.updateRange.offset = offset;
this.attribute.updateRange.count = count;Fix: Use updateRanges (plural) array API:
this.attribute.updateRanges = [{ start: offset, count: count }];Count: 96 addEventListener vs 8 removeEventListener
Risk: DOM nodes retained in memory after disposal
Files with leaks:
src/core/input.ts- Multiple window/document listenerssrc/foliage/post-processing.ts:64- Resize listener never removedsrc/rendering/culling-system.ts- Stats element listeners
Example fix pattern:
// Add disposal method
public dispose(): void {
window.removeEventListener('resize', this.handleResize);
document.removeEventListener('keydown', this.handleKeydown);
}Count: 134 try { vs 95 catch blocks
Risk: Unhandled exceptions crash the application
Files needing attention:
src/systems/save-system.ts- IndexedDB operationssrc/systems/asset-streaming.ts- Network requestssrc/compute/*.ts- WebGPU compute pipelines
Count: 364 usages of any
Files with most any types:
src/foliage/common.ts- TSL function parameters lack typessrc/foliage/foliage-batcher.ts- Batch processing functionssrc/systems/analytics.ts- Event data
Critical in common.ts:
// Lines 117-379 - All Fn() parameters are 'any'
export const triplanarNoise = Fn(([pos, scale]) => { ... })
export const perturbNormal = Fn(([pos, normal, scale, strength]) => { ... })Fix: Add proper types:
export const triplanarNoise = Fn(([pos, scale]: [Node, number]) => { ... })Files:
src/systems/unlocks.ts:70- No try/catch around getItemsrc/utils/startup-profiler.ts:459- Direct localStorage accesssrc/systems/accessibility.ts:511- parse without validation
Risk: Throws in private mode, crashes app
Fix: Wrap all localStorage calls:
try {
const data = localStorage.getItem(key);
return data ? JSON.parse(data) : null;
} catch (e) {
return null;
}Count: 365 console.log/warn/error statements
Recommendation: Replace with structured logger or remove before production
Most verbose files:
src/systems/analytics.ts- Debug loggingsrc/foliage/*-batcher.ts- Initialization logssrc/utils/startup-profiler.ts- Performance logs
Files with .then() without .catch():
src/core/input.ts(12 instances) - Toast importssrc/systems/asset-streaming.ts:1010- Empty catchsrc/workers/*.ts- Worker initialization
Example issue:
import('../utils/toast.js').then(({ showToast }) => {
showToast(message);
}); // No catch - fails silently if module missingFile: src/systems/save-integration-example.ts
71: unlockedAbilities: [], // TODO: Track unlocked abilities
96: const timeOfDay = getTimeOfDay(); // TODO: Implement based on your time system
106: season: 'spring', // TODO: Implement season system
108: moonPhase: 0 // TODO: Implement moon phase tracking
206: // TODO: Connect to your audio system
212: // TODO: Connect to your rendererFile: src/core/input.ts:80-95
const controls = new PointerLockControls(camera, document.body);
const instructions = document.getElementById('instructions');
const startButton = document.getElementById('startButton') as HTMLButtonElement | null;Risk: instructions, startButton could be null
Fix: Add null checks before use
File: src/foliage/animation.ts:250
// distanceToSquared doesn't exist on Color
const dist = color.distanceToSquared(otherColor);Fix: Use color.equals() or color.getHex() === otherColor.getHex()
File: src/examples/asset-streaming-usage.ts:54
Property 'percent' does not exist on type 'LoadingProgress'Fix: Update type definition or use correct property name
File: src/foliage/arpeggio-batcher.ts:296,349
.forEach((dummy) => { ... }) // Parameter 'dummy' implicitly has 'any' type
.map((index, dummy) => { ... }) // Both parameters 'any'File: src/audio/audio-system.ts:117
Issue: All declarations of 'setLoadingStatus' must have identical modifiers
Count: 46 setInterval/setTimeout
Risk: Timers not cleared on component disposal
Recommendation: Track all timers and clear in dispose methods
| Metric | Count | Status |
|---|---|---|
| TypeScript Errors | 100+ | 🔴 Critical |
any types |
364 | 🟠 High |
| Console statements | 365 | 🟡 Medium |
| Event listeners (add) | 96 | 🟠 High |
| Event listeners (remove) | 8 | 🟠 High |
| Try blocks | 134 | 🟡 Medium |
| Catch blocks | 95 | 🟡 Medium |
| setInterval/Timeout | 46 | 🟡 Medium |
| TODO comments | 8 | 🟢 Low |
| debugger statements | 0 | ✅ Good |
- Fix moduleResolution in tsconfig.json
- Add
_scratchVec1declaration in common.ts - Fix
updateRange→updateRangesin dandelion-seeds.ts - Fix SphereGeometry missing arguments
- Add dispose() methods to remove event listeners
- Balance try/catch blocks
- Add localStorage safety wrappers
- Replace console.log with logger utility
- Add Promise.catch() handlers
- Reduce
anytype usage
src/foliage/common.ts- Undefined var, type errorssrc/foliage/dandelion-seeds.ts- API mismatchsrc/core/input.ts- Event leaks, null checkssrc/systems/save-system.ts- Error handlingsrc/compute/*.ts- Module resolutionsrc/audio/audio-system.ts- Declaration conflict