groundswell 0.0.2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +26 -9
- package/dist/cache/cache-key.d.ts +86 -0
- package/dist/cache/cache-key.d.ts.map +1 -0
- package/dist/cache/cache-key.js +204 -0
- package/dist/cache/cache-key.js.map +1 -0
- package/dist/cache/cache.d.ts +104 -0
- package/dist/cache/cache.d.ts.map +1 -0
- package/dist/cache/cache.js +179 -0
- package/dist/cache/cache.js.map +1 -0
- package/{src/cache/index.ts → dist/cache/index.d.ts} +1 -1
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +6 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/core/agent.d.ts +203 -0
- package/dist/core/agent.d.ts.map +1 -0
- package/dist/core/agent.js +833 -0
- package/dist/core/agent.js.map +1 -0
- package/{src/core/context.ts → dist/core/context.d.ts} +16 -67
- package/dist/core/context.d.ts.map +1 -0
- package/dist/core/context.js +80 -0
- package/dist/core/context.js.map +1 -0
- package/dist/core/event-tree.d.ts +72 -0
- package/dist/core/event-tree.d.ts.map +1 -0
- package/dist/core/event-tree.js +211 -0
- package/dist/core/event-tree.js.map +1 -0
- package/{src/core/factory.ts → dist/core/factory.d.ts} +6 -27
- package/dist/core/factory.d.ts.map +1 -0
- package/dist/core/factory.js +110 -0
- package/dist/core/factory.js.map +1 -0
- package/{src/core/index.ts → dist/core/index.d.ts} +2 -10
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +9 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/logger.d.ts +50 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +91 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/mcp-handler.d.ts +127 -0
- package/dist/core/mcp-handler.d.ts.map +1 -0
- package/dist/core/mcp-handler.js +323 -0
- package/dist/core/mcp-handler.js.map +1 -0
- package/dist/core/prompt.d.ts +80 -0
- package/dist/core/prompt.d.ts.map +1 -0
- package/dist/core/prompt.js +120 -0
- package/dist/core/prompt.js.map +1 -0
- package/dist/core/workflow-context.d.ts +61 -0
- package/dist/core/workflow-context.d.ts.map +1 -0
- package/dist/core/workflow-context.js +358 -0
- package/dist/core/workflow-context.js.map +1 -0
- package/dist/core/workflow.d.ts +543 -0
- package/dist/core/workflow.d.ts.map +1 -0
- package/dist/core/workflow.js +986 -0
- package/dist/core/workflow.js.map +1 -0
- package/dist/debugger/event-replayer.d.ts +422 -0
- package/dist/debugger/event-replayer.d.ts.map +1 -0
- package/dist/debugger/event-replayer.js +639 -0
- package/dist/debugger/event-replayer.js.map +1 -0
- package/dist/debugger/index.d.ts +2 -0
- package/dist/debugger/index.d.ts.map +1 -0
- package/{src/debugger/index.ts → dist/debugger/index.js} +1 -0
- package/dist/debugger/index.js.map +1 -0
- package/dist/debugger/tree-debugger.d.ts +240 -0
- package/dist/debugger/tree-debugger.d.ts.map +1 -0
- package/dist/debugger/tree-debugger.js +620 -0
- package/dist/debugger/tree-debugger.js.map +1 -0
- package/dist/decorators/index.d.ts +4 -0
- package/dist/decorators/index.d.ts.map +1 -0
- package/{src/decorators/index.ts → dist/decorators/index.js} +1 -0
- package/dist/decorators/index.js.map +1 -0
- package/dist/decorators/observed-state.d.ts +32 -0
- package/dist/decorators/observed-state.d.ts.map +1 -0
- package/dist/decorators/observed-state.js +79 -0
- package/dist/decorators/observed-state.js.map +1 -0
- package/dist/decorators/step.d.ts +15 -0
- package/dist/decorators/step.d.ts.map +1 -0
- package/dist/decorators/step.js +192 -0
- package/dist/decorators/step.js.map +1 -0
- package/dist/decorators/task.d.ts +50 -0
- package/dist/decorators/task.d.ts.map +1 -0
- package/dist/decorators/task.js +118 -0
- package/dist/decorators/task.js.map +1 -0
- package/dist/examples/index.d.ts +3 -0
- package/dist/examples/index.d.ts.map +1 -0
- package/{src/examples/index.ts → dist/examples/index.js} +1 -0
- package/dist/examples/index.js.map +1 -0
- package/dist/examples/tdd-orchestrator.d.ts +15 -0
- package/dist/examples/tdd-orchestrator.d.ts.map +1 -0
- package/dist/examples/tdd-orchestrator.js +121 -0
- package/dist/examples/tdd-orchestrator.js.map +1 -0
- package/dist/examples/test-cycle-workflow.d.ts +14 -0
- package/dist/examples/test-cycle-workflow.d.ts.map +1 -0
- package/dist/examples/test-cycle-workflow.js +116 -0
- package/dist/examples/test-cycle-workflow.js.map +1 -0
- package/dist/harnesses/claude-code-harness.d.ts +391 -0
- package/dist/harnesses/claude-code-harness.d.ts.map +1 -0
- package/dist/harnesses/claude-code-harness.js +1076 -0
- package/dist/harnesses/claude-code-harness.js.map +1 -0
- package/dist/harnesses/harness-registry.d.ts +440 -0
- package/dist/harnesses/harness-registry.d.ts.map +1 -0
- package/dist/harnesses/harness-registry.js +543 -0
- package/dist/harnesses/harness-registry.js.map +1 -0
- package/dist/harnesses/index.d.ts +12 -0
- package/dist/harnesses/index.d.ts.map +1 -0
- package/dist/harnesses/index.js +11 -0
- package/dist/harnesses/index.js.map +1 -0
- package/dist/harnesses/pi-harness.d.ts +219 -0
- package/dist/harnesses/pi-harness.d.ts.map +1 -0
- package/dist/harnesses/pi-harness.js +676 -0
- package/dist/harnesses/pi-harness.js.map +1 -0
- package/dist/harnesses/pi-schema-converter.d.ts +24 -0
- package/dist/harnesses/pi-schema-converter.d.ts.map +1 -0
- package/dist/harnesses/pi-schema-converter.js +81 -0
- package/dist/harnesses/pi-schema-converter.js.map +1 -0
- package/dist/harnesses/register-defaults.d.ts +24 -0
- package/dist/harnesses/register-defaults.d.ts.map +1 -0
- package/dist/harnesses/register-defaults.js +40 -0
- package/dist/harnesses/register-defaults.js.map +1 -0
- package/dist/harnesses/session-store.d.ts +201 -0
- package/dist/harnesses/session-store.d.ts.map +1 -0
- package/dist/harnesses/session-store.js +254 -0
- package/dist/harnesses/session-store.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +57 -0
- package/dist/index.js.map +1 -0
- package/dist/reflection/index.d.ts +5 -0
- package/dist/reflection/index.d.ts.map +1 -0
- package/{src/reflection/index.ts → dist/reflection/index.js} +1 -1
- package/dist/reflection/index.js.map +1 -0
- package/dist/reflection/reflection.d.ts +84 -0
- package/dist/reflection/reflection.d.ts.map +1 -0
- package/dist/reflection/reflection.js +344 -0
- package/dist/reflection/reflection.js.map +1 -0
- package/dist/tools/index.d.ts +6 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +11 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/introspection.d.ts +165 -0
- package/dist/tools/introspection.d.ts.map +1 -0
- package/dist/tools/introspection.js +324 -0
- package/dist/tools/introspection.js.map +1 -0
- package/dist/types/agent.d.ts +1317 -0
- package/dist/types/agent.d.ts.map +1 -0
- package/dist/types/agent.js +423 -0
- package/dist/types/agent.js.map +1 -0
- package/dist/types/decorators.d.ts +40 -0
- package/dist/types/decorators.d.ts.map +1 -0
- package/dist/types/decorators.js +2 -0
- package/dist/types/decorators.js.map +1 -0
- package/dist/types/error-strategy.d.ts +13 -0
- package/dist/types/error-strategy.d.ts.map +1 -0
- package/dist/types/error-strategy.js +2 -0
- package/dist/types/error-strategy.js.map +1 -0
- package/dist/types/error.d.ts +20 -0
- package/dist/types/error.d.ts.map +1 -0
- package/dist/types/error.js +2 -0
- package/dist/types/error.js.map +1 -0
- package/dist/types/events.d.ts +113 -0
- package/dist/types/events.d.ts.map +1 -0
- package/dist/types/events.js +2 -0
- package/dist/types/events.js.map +1 -0
- package/dist/types/harnesses.d.ts +474 -0
- package/dist/types/harnesses.d.ts.map +1 -0
- package/dist/types/harnesses.js +2 -0
- package/dist/types/harnesses.js.map +1 -0
- package/dist/types/index.d.ts +23 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +8 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/logging.d.ts +24 -0
- package/dist/types/logging.d.ts.map +1 -0
- package/dist/types/logging.js +2 -0
- package/dist/types/logging.js.map +1 -0
- package/dist/types/observer.d.ts +18 -0
- package/dist/types/observer.d.ts.map +1 -0
- package/dist/types/observer.js +2 -0
- package/dist/types/observer.js.map +1 -0
- package/dist/types/prompt.d.ts +31 -0
- package/dist/types/prompt.d.ts.map +1 -0
- package/dist/types/prompt.js +6 -0
- package/dist/types/prompt.js.map +1 -0
- package/dist/types/providers.d.ts +691 -0
- package/dist/types/providers.d.ts.map +1 -0
- package/dist/types/providers.js +14 -0
- package/dist/types/providers.js.map +1 -0
- package/dist/types/reflection.d.ts +96 -0
- package/dist/types/reflection.d.ts.map +1 -0
- package/dist/types/reflection.js +24 -0
- package/dist/types/reflection.js.map +1 -0
- package/dist/types/restart.d.ts +132 -0
- package/dist/types/restart.d.ts.map +1 -0
- package/dist/types/restart.js +2 -0
- package/dist/types/restart.js.map +1 -0
- package/dist/types/sdk-primitives.d.ts +118 -0
- package/dist/types/sdk-primitives.d.ts.map +1 -0
- package/dist/types/sdk-primitives.js +6 -0
- package/dist/types/sdk-primitives.js.map +1 -0
- package/{src/types/snapshot.ts → dist/types/snapshot.d.ts} +5 -5
- package/dist/types/snapshot.d.ts.map +1 -0
- package/dist/types/snapshot.js +2 -0
- package/dist/types/snapshot.js.map +1 -0
- package/dist/types/streaming.d.ts +194 -0
- package/dist/types/streaming.d.ts.map +1 -0
- package/dist/types/streaming.js +67 -0
- package/dist/types/streaming.js.map +1 -0
- package/dist/types/workflow-context.d.ts +275 -0
- package/dist/types/workflow-context.d.ts.map +1 -0
- package/dist/types/workflow-context.js +8 -0
- package/dist/types/workflow-context.js.map +1 -0
- package/dist/types/workflow.d.ts +30 -0
- package/dist/types/workflow.d.ts.map +1 -0
- package/dist/types/workflow.js +2 -0
- package/dist/types/workflow.js.map +1 -0
- package/dist/utils/agent-validation.d.ts +88 -0
- package/dist/utils/agent-validation.d.ts.map +1 -0
- package/dist/utils/agent-validation.js +87 -0
- package/dist/utils/agent-validation.js.map +1 -0
- package/dist/utils/delay.d.ts +7 -0
- package/dist/utils/delay.d.ts.map +1 -0
- package/dist/utils/delay.js +9 -0
- package/dist/utils/delay.js.map +1 -0
- package/dist/utils/harness-config.d.ts +180 -0
- package/dist/utils/harness-config.d.ts.map +1 -0
- package/dist/utils/harness-config.js +311 -0
- package/dist/utils/harness-config.js.map +1 -0
- package/dist/utils/id.d.ts +6 -0
- package/dist/utils/id.d.ts.map +1 -0
- package/dist/utils/id.js +12 -0
- package/dist/utils/id.js.map +1 -0
- package/dist/utils/index.d.ts +13 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +11 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/model-spec.d.ts +110 -0
- package/dist/utils/model-spec.d.ts.map +1 -0
- package/dist/utils/model-spec.js +149 -0
- package/dist/utils/model-spec.js.map +1 -0
- package/dist/utils/observable.d.ts +54 -0
- package/dist/utils/observable.d.ts.map +1 -0
- package/dist/utils/observable.js +82 -0
- package/dist/utils/observable.js.map +1 -0
- package/dist/utils/provider-config.d.ts +10 -0
- package/dist/utils/provider-config.d.ts.map +1 -0
- package/dist/utils/provider-config.js +10 -0
- package/dist/utils/provider-config.js.map +1 -0
- package/dist/utils/restart-analysis.d.ts +202 -0
- package/dist/utils/restart-analysis.d.ts.map +1 -0
- package/dist/utils/restart-analysis.js +426 -0
- package/dist/utils/restart-analysis.js.map +1 -0
- package/dist/utils/session-serialization.d.ts +118 -0
- package/dist/utils/session-serialization.d.ts.map +1 -0
- package/dist/utils/session-serialization.js +217 -0
- package/dist/utils/session-serialization.js.map +1 -0
- package/dist/utils/workflow-error-utils.d.ts +22 -0
- package/dist/utils/workflow-error-utils.d.ts.map +1 -0
- package/dist/utils/workflow-error-utils.js +45 -0
- package/dist/utils/workflow-error-utils.js.map +1 -0
- package/package.json +34 -5
- package/.claude/commands/subtask-planning/prp-base-create.md +0 -120
- package/.claude/commands/subtask-planning/prp-base-execute.md +0 -65
- package/.claude/commands/task-breakdown.md +0 -94
- package/.claude/settings.local.json +0 -9
- package/.claude/system_prompts/task-breakdown.md +0 -101
- package/CHANGELOG.md +0 -188
- package/PRD.md +0 -543
- package/PRPs/001-hierarchical-workflow-engine.md +0 -2438
- package/PRPs/PRDs/002-agent-prompt.md +0 -390
- package/PRPs/PRDs/003-agent-prompt.md +0 -943
- package/PRPs/PRDs/004-agent-prompt.md +0 -1136
- package/PRPs/PRDs/tasks-001.json +0 -492
- package/PRPs/README.md +0 -83
- package/PRPs/templates/prp_base.md +0 -222
- package/docs/agent.md +0 -422
- package/docs/prompt.md +0 -419
- package/docs/workflow.md +0 -600
- package/examples/README.md +0 -258
- package/examples/examples/01-basic-workflow.ts +0 -100
- package/examples/examples/02-decorator-options.ts +0 -217
- package/examples/examples/03-parent-child.ts +0 -241
- package/examples/examples/04-observers-debugger.ts +0 -340
- package/examples/examples/05-error-handling.ts +0 -387
- package/examples/examples/06-concurrent-tasks.ts +0 -352
- package/examples/examples/07-agent-loops.ts +0 -432
- package/examples/examples/08-sdk-features.ts +0 -667
- package/examples/examples/09-reflection.ts +0 -573
- package/examples/examples/10-introspection.ts +0 -550
- package/examples/examples/11-reparenting-workflows.ts +0 -269
- package/examples/index.ts +0 -147
- package/examples/utils/helpers.ts +0 -57
- package/package-lock.json +0 -2398
- package/plan/001_d3bb02af4886/TEST_RESULTS.md +0 -259
- package/plan/001_d3bb02af4886/backlog.json +0 -867
- package/plan/001_d3bb02af4886/bug_fix_tasks.json +0 -484
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M1T1S1/PRP.md +0 -488
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M1T1S2/PRP.md +0 -581
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M1T1S3/PRP.md +0 -687
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S1/PRP.md +0 -492
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/PRP.md +0 -932
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/research/concurrent_error_testing_patterns.md +0 -1109
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/research/vitest_concurrent_testing.md +0 -802
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/research/workflow_engine_test_references.md +0 -603
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T2S1/PRP.md +0 -564
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T2S3/PRP.md +0 -518
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T2S4/PRP.md +0 -1252
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/PRP.md +0 -364
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/research/CODEBASE_INVENTORY.md +0 -114
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/research/DECORATOR_DOCUMENTATION_PATTERNS.md +0 -205
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/research/PRD_LOCATION_ANALYSIS.md +0 -199
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/research/ULTRATHINK_PRP_PLAN.md +0 -134
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S1/PRP.md +0 -495
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S1/research/console_error_inventory.md +0 -435
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S2/PRP.md +0 -506
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S3/PRP.md +0 -612
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T2S2/PRP.md +0 -558
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T2S2/research/external_research.md +0 -788
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T3S2/PRP.md +0 -460
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T3S3/PRP.md +0 -454
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S1/PRP.md +0 -520
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S1/RECOMMENDATION.md +0 -417
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S1/research/external_workflow_engines_research.md +0 -760
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S1/research/security_implications_analysis.md +0 -245
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S2/PRP.md +0 -792
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S1/PRP.md +0 -535
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S1/TEST_EXECUTION_REPORT.md +0 -190
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/PRP.md +0 -654
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/TEST_FIX_REPORT.md +0 -227
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/research/KEY_FINDINGS.md +0 -345
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/research/QUICK_REFERENCE.md +0 -193
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/research/test_maintenance_research.md +0 -1323
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T3S1/BREAKING_CHANGES_AUDIT.md +0 -1011
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T3S1/PRP.md +0 -927
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T3S2/PRP.md +0 -505
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/architecture/logger_child_signature_analysis.md +0 -401
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S3/child_implementation_research.md +0 -142
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S3/test_patterns_research.md +0 -112
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S3/vitest_patterns_research.md +0 -159
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S4/PRP.md +0 -549
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S4/VERIFICATION_REPORT.md +0 -368
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S4/edge_case_analysis.md +0 -172
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S4/usage_inventory.md +0 -175
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T1S2/PRP.md +0 -696
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T1S4/PRP.md +0 -860
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/PRP.md +0 -1066
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/01-testing-aggregated-errors.md +0 -1103
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/01_typescript_error_aggregation_patterns.md +0 -789
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/02-error-merge-strategy-testing-guide.md +0 -1098
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/02_aggregate_error_patterns.md +0 -1037
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/03-promise-allsettled-testing-patterns.md +0 -916
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/03_error_merging_strategies.md +0 -1045
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/04_github_stackoverflow_examples.md +0 -890
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/05_comprehensive_summary.md +0 -822
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/INDEX.md +0 -668
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/QUICK_REFERENCE.md +0 -706
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/README.md +0 -265
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/RESEARCH_REPORT.md +0 -655
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S4/research/vitest_testing_patterns.md +0 -1103
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T3S2/PRP.md +0 -426
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S2/PRP.md +0 -506
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S2/research/QUICK_REFERENCE.md +0 -114
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S2/research/RESEARCH_SUMMARY.md +0 -316
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S2/research/vitest_observer_error_logging_best_practices.md +0 -754
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S3/PRP.md +0 -612
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T2S1/PRP.md +0 -719
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T2S1/README.md +0 -215
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T2S1/analysis.md +0 -765
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T2S3/PRP.md +0 -718
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/DECISION.md +0 -149
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/PRP.md +0 -470
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/research/ULTRATHINK_PLAN.md +0 -332
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/research/codebase_workflow_name_analysis.md +0 -167
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/research/external_best_practices.md +0 -265
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/research/validation_patterns.md +0 -273
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T4S1/workflow_engine_ancestry_api_research.md +0 -760
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T4S3-PRP.md +0 -434
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M4T2S1/PRP.md +0 -717
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M4T2S2/PRP.md +0 -472
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M4T2S2/VALIDATION_REPORT.md +0 -125
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M4T2S2/research/ULTRATHINK_PRP_PLAN.md +0 -301
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/error-logging-best-practices.md +0 -1170
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/research_typescript_partial_and_overloads.md +0 -940
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/vitest-quick-reference.md +0 -151
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/vitest-research.md +0 -650
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/prd_snapshot.md +0 -259
- package/plan/001_d3bb02af4886/bugfix/P1M1T1S1/PRP.md +0 -457
- package/plan/001_d3bb02af4886/bugfix/RESEARCH_SUMMARY.md +0 -346
- package/plan/001_d3bb02af4886/bugfix/architecture/codebase_structure.md +0 -311
- package/plan/001_d3bb02af4886/bugfix/architecture/concurrent_execution_best_practices.md +0 -1565
- package/plan/001_d3bb02af4886/bugfix/architecture/error_handling_patterns.md +0 -288
- package/plan/001_d3bb02af4886/bugfix/architecture/promise_all_analysis.md +0 -741
- package/plan/001_d3bb02af4886/docs/PRP/P1M1T1S4-functional-workflow-error-state-capture-test.md +0 -652
- package/plan/001_d3bb02af4886/docs/PRP/P1P2-PRP.md +0 -527
- package/plan/001_d3bb02af4886/docs/PRP/P3P4-PRP.md +0 -1388
- package/plan/001_d3bb02af4886/docs/PRP/P4P5-PRP.md +0 -1136
- package/plan/001_d3bb02af4886/docs/PRP/PRP.md +0 -527
- package/plan/001_d3bb02af4886/docs/PRP/bugfix/P1M1T2S1-PRP.md +0 -415
- package/plan/001_d3bb02af4886/docs/PRP/bugfix/P1M1T2S2-PRP.md +0 -378
- package/plan/001_d3bb02af4886/docs/PRP/bugfix/P1M1T2S4-PRP.md +0 -713
- package/plan/001_d3bb02af4886/docs/PRP/bugfix/P1M2T1S4-PRP.md +0 -370
- package/plan/001_d3bb02af4886/docs/PRP_P1M3T1S3.md +0 -499
- package/plan/001_d3bb02af4886/docs/TEST_RESULTS.md +0 -230
- package/plan/001_d3bb02af4886/docs/architecture/external_deps.md +0 -358
- package/plan/001_d3bb02af4886/docs/architecture/system_context.md +0 -242
- package/plan/001_d3bb02af4886/docs/bugfix/ANALYSIS_PRD_VS_IMPLEMENTATION.md +0 -1134
- package/plan/001_d3bb02af4886/docs/bugfix/GAP_ANALYSIS_SUMMARY.md +0 -179
- package/plan/001_d3bb02af4886/docs/bugfix/P1M4T2S1/PRP.md +0 -629
- package/plan/001_d3bb02af4886/docs/bugfix/P1M4T2S1/validation-report.md +0 -214
- package/plan/001_d3bb02af4886/docs/bugfix/PRP_P1M4T2S3.md +0 -629
- package/plan/001_d3bb02af4886/docs/bugfix/bugfix_PRP.md +0 -529
- package/plan/001_d3bb02af4886/docs/bugfix/bugfix_QUICK_REFERENCE.md +0 -142
- package/plan/001_d3bb02af4886/docs/bugfix/bugfix_README.md +0 -304
- package/plan/001_d3bb02af4886/docs/bugfix/bugfix_TEST_RESULTS.md +0 -558
- package/plan/001_d3bb02af4886/docs/bugfix/bugfix_VALIDATION_SUMMARY.md +0 -256
- package/plan/001_d3bb02af4886/docs/bugfix/system_context.md +0 -346
- package/plan/001_d3bb02af4886/docs/bugfix-architecture/bug_analysis.md +0 -415
- package/plan/001_d3bb02af4886/docs/bugfix-architecture/implementation_patterns.md +0 -489
- package/plan/001_d3bb02af4886/docs/bugfix-architecture/system_context.md +0 -218
- package/plan/001_d3bb02af4886/docs/bugfix_INITIATION_SUMMARY.md +0 -380
- package/plan/001_d3bb02af4886/docs/research/CYCLE_DETECTION_PATTERNS.md +0 -1923
- package/plan/001_d3bb02af4886/docs/research/CYCLE_DETECTION_QUICK_REF.md +0 -319
- package/plan/001_d3bb02af4886/docs/research/P1M1T2S1/codebase-context.md +0 -115
- package/plan/001_d3bb02af4886/docs/research/P1M1T2S1/cycle-detection-algorithms.md +0 -134
- package/plan/001_d3bb02af4886/docs/research/P1M1T2S1/test-patterns.md +0 -153
- package/plan/001_d3bb02af4886/docs/research/P1M1T2S1/workflow-class.md +0 -132
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/DECORATOR_DOCUMENTATION_BEST_PRACTICES.md +0 -716
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/DECORATOR_DOCUMENTATION_QUICK_REF.md +0 -186
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/GROUNDSWELL_DECORATOR_EXAMPLES.md +0 -604
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/INDEX.md +0 -213
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/codebase_structure.md +0 -30
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/existing_test_pattern.md +0 -56
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/getRootObservers_implementation.md +0 -53
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/test_conventions.md +0 -49
- package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/PRP.md +0 -958
- package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/QUICK_REFERENCE.md +0 -339
- package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/README.md +0 -305
- package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/SUMMARY.md +0 -433
- package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/bidirectional-tree-consistency-testing.md +0 -1574
- package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/test-pattern-examples.md +0 -1014
- package/plan/001_d3bb02af4886/docs/research/P1P2/LRU_CACHE_BEST_PRACTICES.md +0 -1929
- package/plan/001_d3bb02af4886/docs/research/P1P2/LRU_CACHE_CODE_PATTERNS.md +0 -857
- package/plan/001_d3bb02af4886/docs/research/P1P2/LRU_CACHE_INTEGRATION_GUIDE.md +0 -738
- package/plan/001_d3bb02af4886/docs/research/P1P2/LRU_CACHE_RESEARCH_INDEX.md +0 -424
- package/plan/001_d3bb02af4886/docs/research/P1P2/REFLECTION_INDEX.md +0 -291
- package/plan/001_d3bb02af4886/docs/research/P1P2/REFLECTION_RESEARCH_REPORT.md +0 -1342
- package/plan/001_d3bb02af4886/docs/research/P1P2/RESEARCH_SUMMARY.md +0 -342
- package/plan/001_d3bb02af4886/docs/research/P1P2/anthropic-sdk.md +0 -174
- package/plan/001_d3bb02af4886/docs/research/P1P2/async-local-storage.md +0 -200
- package/plan/001_d3bb02af4886/docs/research/P1P2/reflection-code-patterns.md +0 -1205
- package/plan/001_d3bb02af4886/docs/research/P1P2/reflection-decision-matrix.md +0 -421
- package/plan/001_d3bb02af4886/docs/research/P1P2/reflection-implementation-guide.md +0 -1341
- package/plan/001_d3bb02af4886/docs/research/P1P2/reflection-integration-guide.md +0 -834
- package/plan/001_d3bb02af4886/docs/research/P1P2/reflection-patterns.md +0 -1468
- package/plan/001_d3bb02af4886/docs/research/P1P2/reflection-quick-reference.md +0 -558
- package/plan/001_d3bb02af4886/docs/research/P1P2/zod-schema.md +0 -152
- package/plan/001_d3bb02af4886/docs/research/P3P4/caching-lru.md +0 -116
- package/plan/001_d3bb02af4886/docs/research/P3P4/introspection-tools.md +0 -177
- package/plan/001_d3bb02af4886/docs/research/P3P4/reflection-patterns.md +0 -117
- package/plan/001_d3bb02af4886/docs/research/P4P5/RESEARCH_SUMMARY.md +0 -151
- package/plan/001_d3bb02af4886/docs/research/PROMISE_ALLSETTLED_QUICK_REF.md +0 -376
- package/plan/001_d3bb02af4886/docs/research/PROMISE_ALLSETTLED_RESEARCH.md +0 -1507
- package/plan/001_d3bb02af4886/docs/research/bugfix_typescript_patterns.md +0 -949
- package/plan/001_d3bb02af4886/docs/research/error-testing-research.md +0 -619
- package/plan/001_d3bb02af4886/docs/research/error_handling_patterns.md +0 -723
- package/plan/001_d3bb02af4886/docs/research/general/INTROSPECTION_RESEARCH_SUMMARY.md +0 -378
- package/plan/001_d3bb02af4886/docs/research/general/README-INTROSPECTION.md +0 -352
- package/plan/001_d3bb02af4886/docs/research/general/agent-introspection-patterns.md +0 -1085
- package/plan/001_d3bb02af4886/docs/research/general/introspection-security-guide.md +0 -984
- package/plan/001_d3bb02af4886/docs/research/general/introspection-tool-examples.md +0 -875
- package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/PRP_TEMPLATE.md +0 -460
- package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/QUICK_REFERENCE.md +0 -324
- package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/README.md +0 -175
- package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/RESEARCH_REPORT.md +0 -499
- package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/SUMMARY.md +0 -163
- package/plan/001_d3bb02af4886/prd_snapshot.md +0 -543
- package/plan/bugfix/BUG_FIX_SUMMARY.md +0 -961
- package/scripts/generate-llms-full.ts +0 -206
- package/src/__tests__/adversarial/attachChild-performance.test.ts +0 -216
- package/src/__tests__/adversarial/circular-reference.test.ts +0 -101
- package/src/__tests__/adversarial/complex-circular-reference.test.ts +0 -139
- package/src/__tests__/adversarial/concurrent-task-failures.test.ts +0 -571
- package/src/__tests__/adversarial/deep-analysis.test.ts +0 -729
- package/src/__tests__/adversarial/deep-hierarchy-stress.test.ts +0 -213
- package/src/__tests__/adversarial/e2e-prd-validation.test.ts +0 -448
- package/src/__tests__/adversarial/edge-case.test.ts +0 -703
- package/src/__tests__/adversarial/error-merge-strategy.test.ts +0 -760
- package/src/__tests__/adversarial/incremental-performance.test.ts +0 -140
- package/src/__tests__/adversarial/node-map-update-benchmarks.test.ts +0 -457
- package/src/__tests__/adversarial/observer-propagation.test.ts +0 -487
- package/src/__tests__/adversarial/parent-validation.test.ts +0 -143
- package/src/__tests__/adversarial/prd-12-2-compliance.test.ts +0 -611
- package/src/__tests__/adversarial/prd-compliance.test.ts +0 -731
- package/src/__tests__/compatibility/backward-compatibility.test.ts +0 -1572
- package/src/__tests__/helpers/index.ts +0 -18
- package/src/__tests__/helpers/tree-verification.ts +0 -257
- package/src/__tests__/integration/agent-workflow.test.ts +0 -256
- package/src/__tests__/integration/bidirectional-consistency.test.ts +0 -847
- package/src/__tests__/integration/observer-logging.test.ts +0 -643
- package/src/__tests__/integration/tree-mirroring.test.ts +0 -151
- package/src/__tests__/integration/workflow-reparenting.test.ts +0 -303
- package/src/__tests__/unit/agent.test.ts +0 -169
- package/src/__tests__/unit/cache-key.test.ts +0 -182
- package/src/__tests__/unit/cache.test.ts +0 -172
- package/src/__tests__/unit/context.test.ts +0 -217
- package/src/__tests__/unit/decorators.test.ts +0 -100
- package/src/__tests__/unit/introspection-tools.test.ts +0 -277
- package/src/__tests__/unit/logger.test.ts +0 -293
- package/src/__tests__/unit/observable.test.ts +0 -321
- package/src/__tests__/unit/prompt.test.ts +0 -135
- package/src/__tests__/unit/reflection.test.ts +0 -210
- package/src/__tests__/unit/tree-debugger-incremental.test.ts +0 -170
- package/src/__tests__/unit/tree-debugger.test.ts +0 -85
- package/src/__tests__/unit/utils/workflow-error-utils.test.ts +0 -209
- package/src/__tests__/unit/workflow-detachChild.test.ts +0 -100
- package/src/__tests__/unit/workflow-emitEvent-childDetached.test.ts +0 -153
- package/src/__tests__/unit/workflow-isDescendantOf.test.ts +0 -180
- package/src/__tests__/unit/workflow.test.ts +0 -357
- package/src/cache/cache-key.ts +0 -244
- package/src/cache/cache.ts +0 -236
- package/src/core/agent.ts +0 -593
- package/src/core/event-tree.ts +0 -260
- package/src/core/logger.ts +0 -112
- package/src/core/mcp-handler.ts +0 -184
- package/src/core/prompt.ts +0 -150
- package/src/core/workflow-context.ts +0 -351
- package/src/core/workflow.ts +0 -540
- package/src/debugger/tree-debugger.ts +0 -255
- package/src/decorators/observed-state.ts +0 -95
- package/src/decorators/step.ts +0 -139
- package/src/decorators/task.ts +0 -159
- package/src/examples/tdd-orchestrator.ts +0 -65
- package/src/examples/test-cycle-workflow.ts +0 -64
- package/src/index.ts +0 -142
- package/src/reflection/reflection.ts +0 -407
- package/src/tools/index.ts +0 -36
- package/src/tools/introspection.ts +0 -464
- package/src/types/agent.ts +0 -90
- package/src/types/decorators.ts +0 -32
- package/src/types/error-strategy.ts +0 -13
- package/src/types/error.ts +0 -20
- package/src/types/events.ts +0 -75
- package/src/types/index.ts +0 -55
- package/src/types/logging.ts +0 -24
- package/src/types/observer.ts +0 -18
- package/src/types/prompt.ts +0 -40
- package/src/types/reflection.ts +0 -117
- package/src/types/sdk-primitives.ts +0 -128
- package/src/types/workflow-context.ts +0 -163
- package/src/types/workflow.ts +0 -37
- package/src/utils/id.ts +0 -11
- package/src/utils/index.ts +0 -4
- package/src/utils/observable.ts +0 -106
- package/src/utils/workflow-error-utils.ts +0 -56
- package/tsconfig.json +0 -22
- package/vitest.config.ts +0 -16
|
@@ -1,949 +0,0 @@
|
|
|
1
|
-
# TypeScript Best Practices for Array Handling in Error Objects
|
|
2
|
-
|
|
3
|
-
**Research Date:** 2025-01-11
|
|
4
|
-
**Researcher:** Claude Code Agent
|
|
5
|
-
**Purpose:** Comprehensive research on TypeScript patterns for array handling in error objects, specifically for P1M1T1S3 bug fix
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Table of Contents
|
|
10
|
-
|
|
11
|
-
1. [Spread Operator Best Practices](#1-spread-operator-best-practices)
|
|
12
|
-
2. [Type Assertion Patterns](#2-type-assertion-patterns)
|
|
13
|
-
3. [Array Mutation Prevention](#3-array-mutation-prevention)
|
|
14
|
-
4. [LogEntry and Error Object Patterns](#4-logentry-and-error-object-patterns)
|
|
15
|
-
5. [Relevant Documentation URLs](#5-relevant-documentation-urls)
|
|
16
|
-
6. [Code Examples and Patterns](#6-code-examples-and-patterns)
|
|
17
|
-
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
## 1. Spread Operator Best Practices
|
|
21
|
-
|
|
22
|
-
### Core Principles
|
|
23
|
-
|
|
24
|
-
The spread operator (`...`) creates **shallow copies** by default - it copies references to array elements, not the elements themselves. This is critical to understand when working with error objects containing arrays.
|
|
25
|
-
|
|
26
|
-
### Best Practices
|
|
27
|
-
|
|
28
|
-
#### ✅ For Primitive Arrays
|
|
29
|
-
```typescript
|
|
30
|
-
// Works perfectly for primitive values
|
|
31
|
-
const logs = ['error1', 'error2', 'error3'];
|
|
32
|
-
const errorCopy = { ...errorObject, logs: [...logs] };
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
#### ✅ For Object Arrays (Deep Copy)
|
|
36
|
-
```typescript
|
|
37
|
-
// Required for arrays containing objects
|
|
38
|
-
const logEntries = [
|
|
39
|
-
{ timestamp: Date.now(), message: 'error1' },
|
|
40
|
-
{ timestamp: Date.now(), message: 'error2' }
|
|
41
|
-
];
|
|
42
|
-
const errorCopy = {
|
|
43
|
-
...errorObject,
|
|
44
|
-
logs: logEntries.map(entry => ({ ...entry }))
|
|
45
|
-
};
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
#### ✅ Immutable Updates
|
|
49
|
-
```typescript
|
|
50
|
-
// Add to array without mutation
|
|
51
|
-
const updatedError = {
|
|
52
|
-
...errorObject,
|
|
53
|
-
logs: [...errorObject.logs, newLogEntry]
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
// Update specific index
|
|
57
|
-
const withUpdate = {
|
|
58
|
-
...errorObject,
|
|
59
|
-
logs: [
|
|
60
|
-
...errorObject.logs.slice(0, index),
|
|
61
|
-
updatedLog,
|
|
62
|
-
...errorObject.logs.slice(index + 1)
|
|
63
|
-
]
|
|
64
|
-
};
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
### Common Pitfalls
|
|
68
|
-
|
|
69
|
-
#### ❌ Assuming Deep Copy
|
|
70
|
-
```typescript
|
|
71
|
-
// DANGEROUS: Only creates shallow copy
|
|
72
|
-
const errorCopy = { ...errorObject };
|
|
73
|
-
// errorCopy.logs and errorObject.logs reference the SAME array
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
#### ❌ Mutation After Copy
|
|
77
|
-
```typescript
|
|
78
|
-
// DANGEROUS: Mutates shared array reference
|
|
79
|
-
const errorCopy = { ...errorObject };
|
|
80
|
-
errorCopy.logs.push(newLog); // Affects original errorObject too!
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
### Performance Considerations
|
|
84
|
-
|
|
85
|
-
- **Small arrays (<100 elements)**: Spread operator is perfectly fine
|
|
86
|
-
- **Large arrays (>1000 elements)**: Consider performance implications
|
|
87
|
-
- **Frequent operations**: Each spread creates a new array (memory allocation)
|
|
88
|
-
|
|
89
|
-
### Resources
|
|
90
|
-
|
|
91
|
-
- [Spread Operator | TypeScript Guide by Convex](https://www.convex.dev/typescript/advanced/advanced-concepts/typescript-spread-operator)
|
|
92
|
-
- [Spread syntax (...) - JavaScript - MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax)
|
|
93
|
-
- [Unleashing the Power of JavaScript Spread Operator](https://kinsta.com/blog/spread-operator-javascript/)
|
|
94
|
-
- [JavaScript Spread Operator: Advanced Techniques and Best Practices](https://dev.to/hkp22/javascript-spread-operator-advanced-techniques-and-best-practices-5cbn)
|
|
95
|
-
- [Typescript spread deep copy with arrays - Stack Overflow](https://stackoverflow.com/questions/46969895/typescript-spread-deep-copy-with-arrays)
|
|
96
|
-
- [How to Copy Arrays of Objects vs. Arrays of Primitives in TypeScript](https://tevpro.com/how-to-copy-arrays-of-objects-arrays-of-primititives-in-typescript/)
|
|
97
|
-
- [Copying Arrays in TypeScript: Spread vs Deep Linking](https://iamguidozam.blog/2025/12/03/copying-arrays-in-typescript-spread-vs-deep-linking/)
|
|
98
|
-
- [Rest Parameters and Spread Syntax in TypeScript](https://betterstack.com/community/guides/scaling-nodejs/rest-parameters-spread/)
|
|
99
|
-
|
|
100
|
-
---
|
|
101
|
-
|
|
102
|
-
## 2. Type Assertion Patterns
|
|
103
|
-
|
|
104
|
-
### Syntax Options
|
|
105
|
-
|
|
106
|
-
TypeScript provides two syntaxes for type assertions:
|
|
107
|
-
|
|
108
|
-
#### Option 1: `as` Syntax (Recommended)
|
|
109
|
-
```typescript
|
|
110
|
-
const logs = errorObject.logs as LogEntry[];
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
#### Option 2: Angle Bracket Syntax
|
|
114
|
-
```typescript
|
|
115
|
-
const logs = <LogEntry[]>errorObject.logs;
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
**Best Practice:** Prefer the `as` syntax - it's more readable and works better with JSX/TSX files.
|
|
119
|
-
|
|
120
|
-
### When to Use Type Assertions
|
|
121
|
-
|
|
122
|
-
#### ✅ Appropriate Use Cases
|
|
123
|
-
|
|
124
|
-
1. **DOM Manipulation**
|
|
125
|
-
```typescript
|
|
126
|
-
const element = document.getElementById('error-container') as HTMLElement;
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
2. **JSON Parsing**
|
|
130
|
-
```typescript
|
|
131
|
-
const data = JSON.parse(jsonString) as ErrorData;
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
3. **Known API Responses**
|
|
135
|
-
```typescript
|
|
136
|
-
const response = await fetch('/api/errors') as Error[];
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
4. **Better Type Inference**
|
|
140
|
-
```typescript
|
|
141
|
-
const logs = (errorObject.logs || []) as LogEntry[];
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
#### ❌ Avoid Type Assertions When
|
|
145
|
-
|
|
146
|
-
- You can use proper type inference
|
|
147
|
-
- Working with completely unknown data types
|
|
148
|
-
- A type guard would be safer
|
|
149
|
-
- The assertion might mask actual type errors
|
|
150
|
-
|
|
151
|
-
### Best Practices
|
|
152
|
-
|
|
153
|
-
#### 1. Use Type Guards Instead (When Possible)
|
|
154
|
-
```typescript
|
|
155
|
-
function isLogEntryArray(value: unknown): value is LogEntry[] {
|
|
156
|
-
return Array.isArray(value) &&
|
|
157
|
-
value.every(item => 'timestamp' in item && 'message' in item);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
if (isLogEntryArray(errorObject.logs)) {
|
|
161
|
-
// TypeScript now knows errorObject.logs is LogEntry[]
|
|
162
|
-
errorObject.logs.forEach(log => console.log(log.message));
|
|
163
|
-
}
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
#### 2. Combine Assertions with Runtime Validation
|
|
167
|
-
```typescript
|
|
168
|
-
import z from 'zod';
|
|
169
|
-
|
|
170
|
-
const LogEntrySchema = z.object({
|
|
171
|
-
timestamp: z.number(),
|
|
172
|
-
message: z.string()
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
const logs = LogEntrySchema.array().parse(errorObject.logs);
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
#### 3. Use `as const` for Literal Types
|
|
179
|
-
```typescript
|
|
180
|
-
const errorConfig = {
|
|
181
|
-
maxLogs: 100,
|
|
182
|
-
level: 'error'
|
|
183
|
-
} as const;
|
|
184
|
-
// errorConfig.level is typed as 'error', not string
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
#### 4. Understand Compile-time vs Runtime
|
|
188
|
-
```typescript
|
|
189
|
-
const logs = errorObject.logs as LogEntry[];
|
|
190
|
-
// This is removed during compilation - no runtime check!
|
|
191
|
-
// If errorObject.logs is not actually LogEntry[], you get runtime errors
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
### Type Assertion Anti-patterns
|
|
195
|
-
|
|
196
|
-
#### ❌ Over-using Assertions
|
|
197
|
-
```typescript
|
|
198
|
-
// BAD: Defeats TypeScript's type checking
|
|
199
|
-
const data = someUnknownValue as any as ComplexType;
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
#### ❌ Asserting Without Validation
|
|
203
|
-
```typescript
|
|
204
|
-
// DANGEROUS: No runtime validation
|
|
205
|
-
const logs = externalApiResponse.logs as LogEntry[];
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
### Resources
|
|
209
|
-
|
|
210
|
-
- [Mastering Type Assertion in TypeScript: Unleashing the Power of Type Safety](https://dev.to/vjnvisakh/mastering-type-assertion-in-typescript-unleashing-the-power-of-type-safety-364h)
|
|
211
|
-
- [TypeScript Type Assertion: Syntax, Behavior, and Practical Examples](https://mimo.org/glossary/typescript/type-assertion)
|
|
212
|
-
- [Documentation - Everyday Types](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html)
|
|
213
|
-
- [TypeScript: Understanding Type Assertion - Abhishek Wadalkar](https://abhishekw.medium.com/typescript-understanding-type-assertion-c06be90e1ba1)
|
|
214
|
-
- [Type Assertions and Type Casting in TypeScript](https://betterstack.com/community/guides/scaling-nodejs/type-assertions-casting/)
|
|
215
|
-
- [Type Assertion | TypeScript Guide by Convex](https://www.convex.dev/typescript/typescript-101/type-conversion-checking/typescript-type-assertion)
|
|
216
|
-
- [Type Assertion | TypeScript Deep Dive](https://basarat.gitbook.io/typescript/type-system/type-assertion)
|
|
217
|
-
- [Documentation - Advanced Types](https://www.typescriptlang.org/docs/handbook/advanced-types.html)
|
|
218
|
-
- [Avoid using Type Assertions in TypeScript](https://www.allthingstypescript.dev/p/avoid-using-type-assertions-in-typescript)
|
|
219
|
-
|
|
220
|
-
---
|
|
221
|
-
|
|
222
|
-
## 3. Array Mutation Prevention
|
|
223
|
-
|
|
224
|
-
### TypeScript Compile-time Solutions
|
|
225
|
-
|
|
226
|
-
#### 1. `readonly` Modifier
|
|
227
|
-
```typescript
|
|
228
|
-
interface ErrorObject {
|
|
229
|
-
readonly logs: readonly LogEntry[];
|
|
230
|
-
readonly timestamp: number;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
const error: ErrorObject = {
|
|
234
|
-
logs: [],
|
|
235
|
-
timestamp: Date.now()
|
|
236
|
-
};
|
|
237
|
-
|
|
238
|
-
// Compile-time error: Cannot assign to 'logs' because it is read-only
|
|
239
|
-
error.logs.push(newLog);
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
#### 2. `ReadonlyArray<T>` Type
|
|
243
|
-
```typescript
|
|
244
|
-
interface ErrorObject {
|
|
245
|
-
logs: ReadonlyArray<LogEntry>;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
// Prevents:
|
|
249
|
-
// - push(), pop(), splice()
|
|
250
|
-
// - direct index assignment
|
|
251
|
-
// - length modification
|
|
252
|
-
```
|
|
253
|
-
|
|
254
|
-
#### 3. `Readonly<T>` Utility Type
|
|
255
|
-
```typescript
|
|
256
|
-
interface ErrorObject {
|
|
257
|
-
logs: LogEntry[];
|
|
258
|
-
metadata: {
|
|
259
|
-
count: number;
|
|
260
|
-
};
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
type ImmutableError = Readonly<ErrorObject>;
|
|
264
|
-
// All properties become readonly
|
|
265
|
-
```
|
|
266
|
-
|
|
267
|
-
#### 4. Const Assertions
|
|
268
|
-
```typescript
|
|
269
|
-
const initialError = {
|
|
270
|
-
logs: [],
|
|
271
|
-
timestamp: Date.now()
|
|
272
|
-
} as const;
|
|
273
|
-
|
|
274
|
-
// Creates deep readonly type
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
-
### Runtime Solutions
|
|
278
|
-
|
|
279
|
-
#### 1. `Object.freeze()`
|
|
280
|
-
```typescript
|
|
281
|
-
const errorObject = {
|
|
282
|
-
logs: [log1, log2],
|
|
283
|
-
timestamp: Date.now()
|
|
284
|
-
};
|
|
285
|
-
|
|
286
|
-
Object.freeze(errorObject);
|
|
287
|
-
Object.freeze(errorObject.logs);
|
|
288
|
-
|
|
289
|
-
// Runtime errors in strict mode:
|
|
290
|
-
errorObject.logs.push(newLog); // TypeError: Cannot add property
|
|
291
|
-
```
|
|
292
|
-
|
|
293
|
-
#### 2. Deep Freeze Utility
|
|
294
|
-
```typescript
|
|
295
|
-
function deepFreeze<T>(obj: T): T {
|
|
296
|
-
Object.freeze(obj);
|
|
297
|
-
|
|
298
|
-
if (Array.isArray(obj)) {
|
|
299
|
-
obj.forEach(item => deepFreeze(item));
|
|
300
|
-
} else if (obj && typeof obj === 'object') {
|
|
301
|
-
Object.values(obj).forEach(item => deepFreeze(item));
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
return obj;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
const immutableError = deepFreeze(errorObject);
|
|
308
|
-
```
|
|
309
|
-
|
|
310
|
-
### Linting Rules
|
|
311
|
-
|
|
312
|
-
#### ESLint/TypeScript Rules
|
|
313
|
-
```json
|
|
314
|
-
{
|
|
315
|
-
"rules": {
|
|
316
|
-
"@typescript-eslint/prefer-readonly": "error",
|
|
317
|
-
"@typescript-eslint/no-mutating-methods": "error",
|
|
318
|
-
"functional/immutable-data": "error",
|
|
319
|
-
"functional/no-let": "error"
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
```
|
|
323
|
-
|
|
324
|
-
#### TSLint Immutable Rules
|
|
325
|
-
```bash
|
|
326
|
-
npm install tslint-immutable --save-dev
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
### Best Practices for Error Objects
|
|
330
|
-
|
|
331
|
-
#### ✅ Always Copy Arrays in Error Objects
|
|
332
|
-
```typescript
|
|
333
|
-
function addLogToError(error: ErrorObject, log: LogEntry): ErrorObject {
|
|
334
|
-
return {
|
|
335
|
-
...error,
|
|
336
|
-
logs: [...error.logs, log]
|
|
337
|
-
};
|
|
338
|
-
}
|
|
339
|
-
```
|
|
340
|
-
|
|
341
|
-
#### ✅ Use Immutable Methods
|
|
342
|
-
```typescript
|
|
343
|
-
// GOOD: Returns new array
|
|
344
|
-
const filtered = error.logs.filter(log => log.level === 'error');
|
|
345
|
-
|
|
346
|
-
// BAD: Mutates original
|
|
347
|
-
error.logs.splice(0, 1);
|
|
348
|
-
```
|
|
349
|
-
|
|
350
|
-
#### ✅ Combine readonly with Copying
|
|
351
|
-
```typescript
|
|
352
|
-
interface ErrorObject {
|
|
353
|
-
readonly logs: ReadonlyArray<LogEntry>;
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
function createError(logs: LogEntry[]): ErrorObject {
|
|
357
|
-
return {
|
|
358
|
-
logs: [...logs] // Create copy, then make readonly
|
|
359
|
-
};
|
|
360
|
-
}
|
|
361
|
-
```
|
|
362
|
-
|
|
363
|
-
### Anti-patterns to Avoid
|
|
364
|
-
|
|
365
|
-
#### ❌ Direct Mutation
|
|
366
|
-
```typescript
|
|
367
|
-
// DANGEROUS: Mutates shared state
|
|
368
|
-
function logError(error: ErrorObject, message: string) {
|
|
369
|
-
error.logs.push({ timestamp: Date.now(), message });
|
|
370
|
-
}
|
|
371
|
-
```
|
|
372
|
-
|
|
373
|
-
#### ❌ Exposing Mutable References
|
|
374
|
-
```typescript
|
|
375
|
-
// DANGEROUS: Caller can mutate internal array
|
|
376
|
-
class ErrorCollector {
|
|
377
|
-
private logs: LogEntry[] = [];
|
|
378
|
-
|
|
379
|
-
getLogs(): LogEntry[] {
|
|
380
|
-
return this.logs; // Returns mutable reference!
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
// BETTER: Return copy or readonly version
|
|
385
|
-
getLogs(): ReadonlyArray<LogEntry> {
|
|
386
|
-
return [...this.logs];
|
|
387
|
-
}
|
|
388
|
-
```
|
|
389
|
-
|
|
390
|
-
### Resources
|
|
391
|
-
|
|
392
|
-
- [How to prevent object/array mutation? - Stack Overflow](https://stackoverflow.com/questions/34840334/how-to-prevent-object-array-mutation)
|
|
393
|
-
- [Simple Rules for Avoiding Mutation in JavaScript](https://medium.com/@edekobifrank/simple-rules-for-avoiding-mutation-in-javascript-24a492ffeb44)
|
|
394
|
-
- [Stop mutating in map, reduce and forEach](https://dev.to/smeijer/stop-mutating-in-map-reduce-and-foreach-58bf)
|
|
395
|
-
- [TSLint Immutable - GitHub](https://github.com/jonaskello/tslint-immutable)
|
|
396
|
-
- [Understanding readonly in TypeScript](https://betterstack.com/community/guides/scaling-nodejs/ts-readonly/)
|
|
397
|
-
- [Mutability - Total TypeScript](https://www.totaltypescript.com/books/total-typescript-essentials/mutability)
|
|
398
|
-
- [Immutability with Const Assertions](https://typescript.tv/course/06-immutability-with-const-assertions)
|
|
399
|
-
- [Using the readonly Modifier in TypeScript](https://www.convex.dev/typescript/advanced/utility-types-mapped-types/typescript-readonly)
|
|
400
|
-
- [Why you'll love Typescript's ReadonlyArray](https://itnext.io/why-youll-love-typescript-s-readonlyarray-9d7f09971e4a)
|
|
401
|
-
- [Readonly Arrays in TypeScript](https://typestronglab.in/tutorial/readonly-arrays)
|
|
402
|
-
- [Handling readonly in TypeScript vs JavaScript](https://gist.github.com/dfkaye/9789c41a7d438355d564a186dc87c1f0)
|
|
403
|
-
- [A brief introduction to "Data Immutability" in TypeScript](https://medium.com/jspoint/typescript-data-immutability-71dc3e604426)
|
|
404
|
-
- [Readonly | TypeScript Deep Dive](https://basarat.gitbook.io/typescript/type-system/readonly)
|
|
405
|
-
|
|
406
|
-
---
|
|
407
|
-
|
|
408
|
-
## 4. LogEntry and Error Object Patterns
|
|
409
|
-
|
|
410
|
-
### LogEntry Interface Patterns
|
|
411
|
-
|
|
412
|
-
#### Basic LogEntry Pattern
|
|
413
|
-
```typescript
|
|
414
|
-
interface LogEntry {
|
|
415
|
-
timestamp: number;
|
|
416
|
-
message: string;
|
|
417
|
-
level?: 'info' | 'warn' | 'error';
|
|
418
|
-
context?: Record<string, unknown>;
|
|
419
|
-
}
|
|
420
|
-
```
|
|
421
|
-
|
|
422
|
-
#### Enhanced LogEntry with Metadata
|
|
423
|
-
```typescript
|
|
424
|
-
interface LogEntry {
|
|
425
|
-
timestamp: number;
|
|
426
|
-
message: string;
|
|
427
|
-
level: LogLevel;
|
|
428
|
-
category: string;
|
|
429
|
-
context?: Readonly<Record<string, unknown>>;
|
|
430
|
-
stack?: string;
|
|
431
|
-
userId?: string;
|
|
432
|
-
requestId?: string;
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'fatal';
|
|
436
|
-
```
|
|
437
|
-
|
|
438
|
-
### Error Object Patterns
|
|
439
|
-
|
|
440
|
-
#### Pattern 1: Simple Error Object
|
|
441
|
-
```typescript
|
|
442
|
-
interface ErrorObject {
|
|
443
|
-
message: string;
|
|
444
|
-
logs: ReadonlyArray<LogEntry>;
|
|
445
|
-
timestamp: number;
|
|
446
|
-
}
|
|
447
|
-
```
|
|
448
|
-
|
|
449
|
-
#### Pattern 2: Hierarchical Error Object
|
|
450
|
-
```typescript
|
|
451
|
-
interface ErrorObject {
|
|
452
|
-
id: string;
|
|
453
|
-
type: ErrorType;
|
|
454
|
-
message: string;
|
|
455
|
-
logs: ReadonlyArray<LogEntry>;
|
|
456
|
-
metadata: Readonly<ErrorMetadata>;
|
|
457
|
-
cause?: ErrorObject;
|
|
458
|
-
timestamp: number;
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
interface ErrorMetadata {
|
|
462
|
-
userId?: string;
|
|
463
|
-
sessionId?: string;
|
|
464
|
-
requestId?: string;
|
|
465
|
-
environment: 'development' | 'staging' | 'production';
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
type ErrorType =
|
|
469
|
-
| 'validation'
|
|
470
|
-
| 'network'
|
|
471
|
-
| 'runtime'
|
|
472
|
-
| 'business'
|
|
473
|
-
| 'unknown';
|
|
474
|
-
```
|
|
475
|
-
|
|
476
|
-
#### Pattern 3: Functional Error Result
|
|
477
|
-
```typescript
|
|
478
|
-
type Result<T, E extends ErrorObject> =
|
|
479
|
-
| { success: true; data: T }
|
|
480
|
-
| { success: false; error: E };
|
|
481
|
-
|
|
482
|
-
async function fetchData(): Promise<Result<Data, ErrorObject>> {
|
|
483
|
-
try {
|
|
484
|
-
const data = await apiCall();
|
|
485
|
-
return { success: true, data };
|
|
486
|
-
} catch (error) {
|
|
487
|
-
return {
|
|
488
|
-
success: false,
|
|
489
|
-
error: {
|
|
490
|
-
id: generateId(),
|
|
491
|
-
type: 'network',
|
|
492
|
-
message: error.message,
|
|
493
|
-
logs: [],
|
|
494
|
-
metadata: {
|
|
495
|
-
environment: 'production'
|
|
496
|
-
},
|
|
497
|
-
timestamp: Date.now()
|
|
498
|
-
}
|
|
499
|
-
};
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
|
-
```
|
|
503
|
-
|
|
504
|
-
### Logging System Patterns
|
|
505
|
-
|
|
506
|
-
#### Pattern 1: Immutable Logger
|
|
507
|
-
```typescript
|
|
508
|
-
class Logger {
|
|
509
|
-
private readonly logs: ReadonlyArray<LogEntry>;
|
|
510
|
-
|
|
511
|
-
constructor(logs: LogEntry[] = []) {
|
|
512
|
-
this.logs = Object.freeze([...logs]);
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
addLog(entry: LogEntry): Logger {
|
|
516
|
-
return new Logger([...this.logs, entry]);
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
getLogs(): ReadonlyArray<LogEntry> {
|
|
520
|
-
return this.logs;
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
filter(predicate: (log: LogEntry) => boolean): Logger {
|
|
524
|
-
return new Logger(this.logs.filter(predicate));
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
```
|
|
528
|
-
|
|
529
|
-
#### Pattern 2: Error Collector
|
|
530
|
-
```typescript
|
|
531
|
-
class ErrorCollector {
|
|
532
|
-
private readonly errors: ReadonlyArray<ErrorObject>;
|
|
533
|
-
|
|
534
|
-
constructor(errors: ErrorObject[] = []) {
|
|
535
|
-
this.errors = Object.freeze([...errors]);
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
addError(error: ErrorObject): ErrorCollector {
|
|
539
|
-
return new ErrorCollector([...this.errors, error]);
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
addLogToLastError(log: LogEntry): ErrorCollector {
|
|
543
|
-
if (this.errors.length === 0) {
|
|
544
|
-
return this;
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
const lastError = this.errors[this.errors.length - 1];
|
|
548
|
-
const updatedLastError: ErrorObject = {
|
|
549
|
-
...lastError,
|
|
550
|
-
logs: [...lastError.logs, log]
|
|
551
|
-
};
|
|
552
|
-
|
|
553
|
-
return new ErrorCollector([
|
|
554
|
-
...this.errors.slice(0, -1),
|
|
555
|
-
updatedLastError
|
|
556
|
-
]);
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
```
|
|
560
|
-
|
|
561
|
-
### Error Handling Best Practices
|
|
562
|
-
|
|
563
|
-
#### 1. Always Initialize Empty Arrays
|
|
564
|
-
```typescript
|
|
565
|
-
// GOOD: Safe default
|
|
566
|
-
function createError(message: string): ErrorObject {
|
|
567
|
-
return {
|
|
568
|
-
message,
|
|
569
|
-
logs: [], // Always initialize
|
|
570
|
-
timestamp: Date.now()
|
|
571
|
-
};
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
// BAD: Undefined logs
|
|
575
|
-
interface BadErrorObject {
|
|
576
|
-
message: string;
|
|
577
|
-
logs?: LogEntry[]; // Optional leads to constant null checks
|
|
578
|
-
}
|
|
579
|
-
```
|
|
580
|
-
|
|
581
|
-
#### 2. Use Readonly for Public APIs
|
|
582
|
-
```typescript
|
|
583
|
-
class ErrorHandler {
|
|
584
|
-
private logs: LogEntry[] = [];
|
|
585
|
-
|
|
586
|
-
// Public API returns readonly
|
|
587
|
-
getLogs(): ReadonlyArray<LogEntry> {
|
|
588
|
-
return this.logs;
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
// Returns new instance
|
|
592
|
-
withLog(log: LogEntry): ErrorHandler {
|
|
593
|
-
const newInstance = new ErrorHandler();
|
|
594
|
-
newInstance.logs = [...this.logs, log];
|
|
595
|
-
return newInstance;
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
```
|
|
599
|
-
|
|
600
|
-
#### 3. Type Guard Validation
|
|
601
|
-
```typescript
|
|
602
|
-
function isValidLogEntry(entry: unknown): entry is LogEntry {
|
|
603
|
-
return (
|
|
604
|
-
typeof entry === 'object' &&
|
|
605
|
-
entry !== null &&
|
|
606
|
-
'timestamp' in entry &&
|
|
607
|
-
'message' in entry &&
|
|
608
|
-
typeof (entry as LogEntry).timestamp === 'number' &&
|
|
609
|
-
typeof (entry as LogEntry).message === 'string'
|
|
610
|
-
);
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
function safeAddLog(error: ErrorObject, entry: unknown): ErrorObject {
|
|
614
|
-
if (!isValidLogEntry(entry)) {
|
|
615
|
-
return error;
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
return {
|
|
619
|
-
...error,
|
|
620
|
-
logs: [...error.logs, entry]
|
|
621
|
-
};
|
|
622
|
-
}
|
|
623
|
-
```
|
|
624
|
-
|
|
625
|
-
#### 4. Immutable Error Builders
|
|
626
|
-
```typescript
|
|
627
|
-
class ErrorBuilder {
|
|
628
|
-
private readonly error: Partial<ErrorObject>;
|
|
629
|
-
|
|
630
|
-
constructor() {
|
|
631
|
-
this.error = {
|
|
632
|
-
logs: [],
|
|
633
|
-
timestamp: Date.now()
|
|
634
|
-
};
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
withMessage(message: string): ErrorBuilder {
|
|
638
|
-
return new ErrorBuilder({
|
|
639
|
-
...this.error,
|
|
640
|
-
message
|
|
641
|
-
});
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
withLog(log: LogEntry): ErrorBuilder {
|
|
645
|
-
return new ErrorBuilder({
|
|
646
|
-
...this.error,
|
|
647
|
-
logs: [...(this.error.logs || []), log]
|
|
648
|
-
});
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
build(): ErrorObject {
|
|
652
|
-
if (!this.error.message || !this.error.logs) {
|
|
653
|
-
throw new Error('Invalid error object');
|
|
654
|
-
}
|
|
655
|
-
|
|
656
|
-
return {
|
|
657
|
-
...this.error,
|
|
658
|
-
logs: Object.freeze([...this.error.logs])
|
|
659
|
-
} as ErrorObject;
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
```
|
|
663
|
-
|
|
664
|
-
### Resources
|
|
665
|
-
|
|
666
|
-
- [Error Handling in TypeScript: Best Practices](https://medium.com/@arreyetta/error-handling-in-typescript-best-practices-80cdfe6d06db)
|
|
667
|
-
- [Handling errors like a pro in TypeScript](https://engineering.udacity.com/handling-errors-like-a-pro-in-typescript-d7a314ad4991)
|
|
668
|
-
- [TypeScript Error Handling: Tips and Best Practices](https://hupp.tech/blog/typescript/typescript-error-handling-tips-and-best-practices/)
|
|
669
|
-
- [JavaScript/TypeScript Error Handling: How Much Do You Know](https://betacraft.com/2025-01-15-js-ts-error-handling/)
|
|
670
|
-
- [Advanced Error Handling in TypeScript: Best Practices and Common Pitfalls](https://overctrl.com/advanced-error-handling-in-typescript-best-practices-and-common-pitfalls/)
|
|
671
|
-
- [The 5 commandments of clean error handling in TypeScript](https://backstage.orus.eu/the-5-commandments-of-clean-error-handling-in-typescript/)
|
|
672
|
-
- [TypeScript Error Handling](https://www.w3schools.com/typescript/typescript_error_handling.php)
|
|
673
|
-
- [How to Efficiently Handle Errors in TypeScript](https://dev.to/info_generalhazedawn_a3d/how-to-efficiently-handle-errors-in-typescript-3gf8)
|
|
674
|
-
- [Best Practices for Client-Side Logging and Error Handling in React](https://www.loggly.com/blog/best-practices-for-client-side-logging-and-error-handling-in-react/)
|
|
675
|
-
- [Understanding Error Handling in TypeScript: Strategies and Best Practices](https://blogs.perficient.com/2024/06/26/understanding-error-handling-in-typescript-strategies-and-best-practices/)
|
|
676
|
-
- [Building an Efficient Logging System for React + TypeScript](https://medium.com/@genildocs/building-an-efficient-logging-system-for-react-typescript-applications-3f000480a843)
|
|
677
|
-
- [Simple JavaScript Logger in TypeScript](https://blog.hellojs.org/simple-javascript-logger-in-typescript-demonstrating-interfaces-union-types-and-rest-parameters-6efc5aee2c97)
|
|
678
|
-
- [No more Try/Catch: a better way to handle errors in TypeScript](https://dev.to/noah-00/no-more-trycatch-a-better-way-to-handle-errors-in-typescript-5hbd)
|
|
679
|
-
|
|
680
|
-
---
|
|
681
|
-
|
|
682
|
-
## 5. Relevant Documentation URLs
|
|
683
|
-
|
|
684
|
-
### Official TypeScript Documentation
|
|
685
|
-
- [TypeScript Handbook - Everyday Types](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html)
|
|
686
|
-
- [TypeScript Handbook - Advanced Types](https://www.typescriptlang.org/docs/handbook/advanced-types.html)
|
|
687
|
-
- [TypeScript 3.4 Release Notes - ReadonlyArray](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3.4.html)
|
|
688
|
-
|
|
689
|
-
### TypeScript Community Resources
|
|
690
|
-
- [TypeScript Deep Dive](https://basarat.gitbook.io/typescript/)
|
|
691
|
-
- [Total TypeScript](https://www.totaltypescript.com/)
|
|
692
|
-
- [TypeScript TV](https://typescript.tv/)
|
|
693
|
-
|
|
694
|
-
### JavaScript/MDN Documentation
|
|
695
|
-
- [Spread syntax (...) - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax)
|
|
696
|
-
- [Object.freeze() - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze)
|
|
697
|
-
|
|
698
|
-
### Tooling
|
|
699
|
-
- [TSLint Immutable](https://github.com/jonaskello/tslint-immutable)
|
|
700
|
-
- [ESLint TypeScript Rules](https://typescript-eslint.io/rules/)
|
|
701
|
-
|
|
702
|
-
---
|
|
703
|
-
|
|
704
|
-
## 6. Code Examples and Patterns
|
|
705
|
-
|
|
706
|
-
### Pattern 1: Safe Error Object Creation
|
|
707
|
-
```typescript
|
|
708
|
-
interface LogEntry {
|
|
709
|
-
timestamp: number;
|
|
710
|
-
message: string;
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
interface ErrorObject {
|
|
714
|
-
message: string;
|
|
715
|
-
logs: ReadonlyArray<LogEntry>;
|
|
716
|
-
timestamp: number;
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
// GOOD: Always initialize with empty array
|
|
720
|
-
function createErrorObject(message: string): ErrorObject {
|
|
721
|
-
return {
|
|
722
|
-
message,
|
|
723
|
-
logs: [],
|
|
724
|
-
timestamp: Date.now()
|
|
725
|
-
};
|
|
726
|
-
}
|
|
727
|
-
|
|
728
|
-
// GOOD: Safe log addition
|
|
729
|
-
function addLog(error: ErrorObject, log: LogEntry): ErrorObject {
|
|
730
|
-
return {
|
|
731
|
-
...error,
|
|
732
|
-
logs: [...error.logs, log]
|
|
733
|
-
};
|
|
734
|
-
}
|
|
735
|
-
```
|
|
736
|
-
|
|
737
|
-
### Pattern 2: Immutable Error Handler
|
|
738
|
-
```typescript
|
|
739
|
-
class ErrorHandler {
|
|
740
|
-
private readonly errors: ReadonlyArray<ErrorObject>;
|
|
741
|
-
|
|
742
|
-
constructor(errors: ErrorObject[] = []) {
|
|
743
|
-
this.errors = Object.freeze([...errors]);
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
addError(error: ErrorObject): ErrorHandler {
|
|
747
|
-
return new ErrorHandler([...this.errors, error]);
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
getErrors(): ReadonlyArray<ErrorObject> {
|
|
751
|
-
return this.errors;
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
getLast(): ErrorObject | undefined {
|
|
755
|
-
return this.errors[this.errors.length - 1];
|
|
756
|
-
}
|
|
757
|
-
}
|
|
758
|
-
```
|
|
759
|
-
|
|
760
|
-
### Pattern 3: Type-Safe Log Addition
|
|
761
|
-
```typescript
|
|
762
|
-
function addLogWithErrorHandling(
|
|
763
|
-
error: ErrorObject | null,
|
|
764
|
-
log: LogEntry
|
|
765
|
-
): ErrorObject {
|
|
766
|
-
// Handle null/undefined error object
|
|
767
|
-
if (!error) {
|
|
768
|
-
return {
|
|
769
|
-
message: 'Unknown error',
|
|
770
|
-
logs: [log],
|
|
771
|
-
timestamp: Date.now()
|
|
772
|
-
};
|
|
773
|
-
}
|
|
774
|
-
|
|
775
|
-
// Handle missing logs array
|
|
776
|
-
const currentLogs = error.logs || [];
|
|
777
|
-
|
|
778
|
-
// Return new immutable error object
|
|
779
|
-
return {
|
|
780
|
-
...error,
|
|
781
|
-
logs: [...currentLogs, log]
|
|
782
|
-
};
|
|
783
|
-
}
|
|
784
|
-
```
|
|
785
|
-
|
|
786
|
-
### Pattern 4: Deep Copy for Nested Objects
|
|
787
|
-
```typescript
|
|
788
|
-
interface LogEntry {
|
|
789
|
-
timestamp: number;
|
|
790
|
-
message: string;
|
|
791
|
-
metadata?: Record<string, unknown>;
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
function deepCopyLogEntry(entry: LogEntry): LogEntry {
|
|
795
|
-
return {
|
|
796
|
-
...entry,
|
|
797
|
-
metadata: entry.metadata ? { ...entry.metadata } : undefined
|
|
798
|
-
};
|
|
799
|
-
}
|
|
800
|
-
|
|
801
|
-
function deepCopyLogs(logs: LogEntry[]): LogEntry[] {
|
|
802
|
-
return logs.map(deepCopyLogEntry);
|
|
803
|
-
}
|
|
804
|
-
```
|
|
805
|
-
|
|
806
|
-
### Pattern 5: Runtime Validation
|
|
807
|
-
```typescript
|
|
808
|
-
function isLogEntry(value: unknown): value is LogEntry {
|
|
809
|
-
if (typeof value !== 'object' || value === null) {
|
|
810
|
-
return false;
|
|
811
|
-
}
|
|
812
|
-
|
|
813
|
-
const entry = value as Record<string, unknown>;
|
|
814
|
-
|
|
815
|
-
return (
|
|
816
|
-
typeof entry.timestamp === 'number' &&
|
|
817
|
-
typeof entry.message === 'string'
|
|
818
|
-
);
|
|
819
|
-
}
|
|
820
|
-
|
|
821
|
-
function safeAddLog(
|
|
822
|
-
error: ErrorObject,
|
|
823
|
-
logEntry: unknown
|
|
824
|
-
): ErrorObject {
|
|
825
|
-
if (!isLogEntry(logEntry)) {
|
|
826
|
-
console.error('Invalid log entry:', logEntry);
|
|
827
|
-
return error;
|
|
828
|
-
}
|
|
829
|
-
|
|
830
|
-
return {
|
|
831
|
-
...error,
|
|
832
|
-
logs: [...error.logs, logEntry]
|
|
833
|
-
};
|
|
834
|
-
}
|
|
835
|
-
```
|
|
836
|
-
|
|
837
|
-
---
|
|
838
|
-
|
|
839
|
-
## Summary and Key Takeaways
|
|
840
|
-
|
|
841
|
-
### For P1M1T1S3 Bug Fix
|
|
842
|
-
|
|
843
|
-
1. **Always Initialize Arrays**: Error objects should always have an initialized `logs: []` array, never `undefined` or optional.
|
|
844
|
-
|
|
845
|
-
2. **Use Spread Operator Correctly**: Remember that spread creates shallow copies. For error objects with arrays, always spread the array: `logs: [...error.logs]`
|
|
846
|
-
|
|
847
|
-
3. **Prevent Mutation**: Use `readonly` modifiers and `ReadonlyArray` types to prevent accidental mutations at compile time.
|
|
848
|
-
|
|
849
|
-
4. **Return New Objects**: Never mutate existing error objects. Always return new instances with updated arrays.
|
|
850
|
-
|
|
851
|
-
5. **Type Safety**: Use type guards and runtime validation when dealing with external data or unknown types.
|
|
852
|
-
|
|
853
|
-
### Recommended Pattern for Groundswell
|
|
854
|
-
|
|
855
|
-
```typescript
|
|
856
|
-
interface LogEntry {
|
|
857
|
-
timestamp: number;
|
|
858
|
-
message: string;
|
|
859
|
-
}
|
|
860
|
-
|
|
861
|
-
interface ErrorObject {
|
|
862
|
-
message: string;
|
|
863
|
-
logs: ReadonlyArray<LogEntry>; // Always defined, readonly
|
|
864
|
-
timestamp: number;
|
|
865
|
-
}
|
|
866
|
-
|
|
867
|
-
function addLogToError(
|
|
868
|
-
error: ErrorObject,
|
|
869
|
-
log: LogEntry
|
|
870
|
-
): ErrorObject {
|
|
871
|
-
return {
|
|
872
|
-
...error,
|
|
873
|
-
logs: [...error.logs, log] // Always copy, never mutate
|
|
874
|
-
};
|
|
875
|
-
}
|
|
876
|
-
```
|
|
877
|
-
|
|
878
|
-
---
|
|
879
|
-
|
|
880
|
-
## Research Sources
|
|
881
|
-
|
|
882
|
-
### Spread Operator Resources
|
|
883
|
-
- [Spread Operator | TypeScript Guide by Convex](https://www.convex.dev/typescript/advanced/advanced-concepts/typescript-spread-operator)
|
|
884
|
-
- [9 TypeScript Best Practices to Take Your Skills to the Next Level](https://medium.com/@kaant43/9-typescript-best-practices-to-take-your-skills-to-the-next-level-18f85fbb7fb1)
|
|
885
|
-
- [Unleashing the Power of JavaScript Spread Operator](https://kinsta.com/blog/spread-operator-javascript/)
|
|
886
|
-
- [Typescript spread deep copy with arrays](https://stackoverflow.com/questions/46969895/typescript-spread-deep-copy-with-arrays)
|
|
887
|
-
- [How to Copy Arrays of Objects vs. Arrays of Primitives in TypeScript](https://tevpro.com/how-to-copy-arrays-of-objects-arrays-of-primititives-in-typescript/)
|
|
888
|
-
- [JavaScript Spread Operator: Advanced Techniques and Best Practices](https://dev.to/hkp22/javascript-spread-operator-advanced-techniques-and-best-practices-5cbn)
|
|
889
|
-
- [Copying Arrays in TypeScript: Spread vs Deep Linking](https://iamguidozam.blog/2025/12/03/copying-arrays-in-typescript-spread-vs-deep-linking/)
|
|
890
|
-
- [Spread syntax (...) - JavaScript - MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax)
|
|
891
|
-
- [Unlock the Power of JavaScript's Spread Operator: A Deep Dive](https://apurvupadhyay.medium.com/unlock-the-power-of-javascripts-spread-operator-a-deep-dive-c5c63d30a2e7)
|
|
892
|
-
- [Rest Parameters and Spread Syntax in TypeScript](https://betterstack.com/community/guides/scaling-nodejs/rest-parameters-spread/)
|
|
893
|
-
|
|
894
|
-
### Type Assertion Resources
|
|
895
|
-
- [Mastering Type Assertion in TypeScript: Unleashing the Power of Type Safety](https://dev.to/vjnvisakh/mastering-type-assertion-in-typescript-unleashing-the-power-of-type-safety-364h)
|
|
896
|
-
- [TypeScript Type Assertion: Syntax, Behavior, and Practical Examples](https://mimo.org/glossary/typescript/type-assertion)
|
|
897
|
-
- [Documentation - Everyday Types](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html)
|
|
898
|
-
- [TypeScript: Understanding Type Assertion](https://abhishekw.medium.com/typescript-understanding-type-assertion-c06be90e1ba1)
|
|
899
|
-
- [Type Assertions and Type Casting in TypeScript](https://betterstack.com/community/guides/scaling-nodejs/type-assertions-casting/)
|
|
900
|
-
- [Type Assertion | TypeScript Guide by Convex](https://www.convex.dev/typescript/typescript-101/type-conversion-checking/typescript-type-assertion)
|
|
901
|
-
- [Type Assertion | TypeScript Deep Dive](https://basarat.gitbook.io/typescript/type-system/type-assertion)
|
|
902
|
-
- [Documentation - Advanced Types](https://www.typescriptlang.org/docs/handbook/advanced-types.html)
|
|
903
|
-
- [Avoid using Type Assertions in TypeScript](https://www.allthingstypescript.dev/p/avoid-using-type-assertions-in-typescript)
|
|
904
|
-
- [What is a good use of type assertions?](https://www.reddit.com/r/typescript/comments/1psvk03/what_is_a_good_use-of-type_assertions/)
|
|
905
|
-
|
|
906
|
-
### Array Mutation Prevention Resources
|
|
907
|
-
- [How to prevent object/array mutation?](https://stackoverflow.com/questions/34840334/how-to-prevent-object-array-mutation)
|
|
908
|
-
- [Simple Rules for Avoiding Mutation in JavaScript](https://medium.com/@edekobifrank/simple-rules-for-avoiding-mutation-in-javascript-24a492ffeb44)
|
|
909
|
-
- [Stop mutating in map, reduce and forEach](https://dev.to/smeijer/stop-mutating-in-map-reduce-and-foreach-58bf)
|
|
910
|
-
- [TSLint Immutable](https://github.com/jonaskello/tslint-immutable)
|
|
911
|
-
- [Understanding readonly in TypeScript](https://betterstack.com/community/guides/scaling-nodejs/ts-readonly/)
|
|
912
|
-
- [Mutability - Total TypeScript](https://www.totaltypescript.com/books/total-typescript-essentials/mutability)
|
|
913
|
-
- [Immutability with Const Assertions](https://typescript.tv/course/06-immutability-with-const-assertions)
|
|
914
|
-
- [Using the readonly Modifier in TypeScript](https://www.convex.dev/typescript/advanced/utility-types-mapped-types/typescript-readonly)
|
|
915
|
-
- [Why you'll love Typescript's ReadonlyArray](https://itnext.io/why-youll-love-typescript-s-readonlyarray-9d7f09971e4a)
|
|
916
|
-
- [TypeScript return immutable/const/readonly Array](https://stackoverflow.com/questions/50003095/typescript-return-immutable-const-readonly-array)
|
|
917
|
-
- [Readonly Arrays in TypeScript](https://typestronglab.in/tutorial/readonly-arrays)
|
|
918
|
-
- [Handling readonly in TypeScript vs JavaScript](https://gist.github.com/dfkaye/9789c41a7d438355d564a186dc87c1f0)
|
|
919
|
-
- [A brief introduction to "Data Immutability" in TypeScript](https://medium.com/jspoint/typescript-data-immutability-71dc3e604426)
|
|
920
|
-
- [Readonly | TypeScript Deep Dive](https://basarat.gitbook.io/typescript/type-system/readonly)
|
|
921
|
-
- [Experiment: Making TypeScript immutable-by-default](https://news.ycombinator.com/item?id=45966018)
|
|
922
|
-
- [Documentation - TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3.4.html)
|
|
923
|
-
- [Avoiding runtime errors with array indexing in TypeScript](https://blog.ignacemaes.com/avoiding-runtime-errors-with-array-indexing-in-typescript/)
|
|
924
|
-
|
|
925
|
-
### Error Handling and Logging Resources
|
|
926
|
-
- [Print | TypeScript Guide by Convex](https://www.convex.dev/typescript/best-practices/error-handling-debugging/typescript-print)
|
|
927
|
-
- [Building an Efficient Logging System for React + TypeScript](https://medium.com/@genildocs/building-an-efficient-logging-system-for-react-typescript-applications-3f000480a843)
|
|
928
|
-
- [Handling errors like a pro in TypeScript](https://engineering.udacity.com/handling-errors-like-a-pro-in-typescript-d7a314ad4991)
|
|
929
|
-
- [No more Try/Catch: a better way to handle errors in TypeScript](https://dev.to/noah-00/no-more-trycatch-a-better-way-to-handle-errors-in-typescript-5hbd)
|
|
930
|
-
- [What are the best practices to log an error?](https://stackoverflow.com/questions/296150/what-are-the-best-practices-to-log-an-error)
|
|
931
|
-
- [Understanding Error Handling in TypeScript: Strategies and Best Practices](https://blogs.perficient.com/2024/06/26/understanding-error-handling-in-typescript-strategies-and-best-practices/)
|
|
932
|
-
- [Simple JavaScript Logger in TypeScript](https://blog.hellojs.org/simple-javascript-logger-in-typescript-demonstrating-interfaces-union-types-and-rest-parameters-6efc5aee2c97)
|
|
933
|
-
- [How to Improve Error Handling in TypeScript](https://www.linkedin.com/posts/afaqjaved_typescript-errorhandling-functionalprogramming-activity-7382342152154017792-9gIy)
|
|
934
|
-
- [TypeScript Error Handling](https://www.w3schools.com/typescript/typescript_error_handling.php)
|
|
935
|
-
- [Mastering Data Validation and Error Handling](https://blog.codeminer42.com/zod-validation-101/)
|
|
936
|
-
- [Error Handling in TypeScript: Best Practices](https://medium.com/@arreyetta/error-handling-in-typescript-best-practices-80cdfe6d06db)
|
|
937
|
-
- [TypeScript Error Handling: Tips and Best Practices](https://hupp.tech/blog/typescript/typescript-error-handling-tips-and-best-practices/)
|
|
938
|
-
- [JavaScript/TypeScript Error Handling](https://betacraft.com/2025-01-15-js-ts-error-handling/)
|
|
939
|
-
- [A better way to handle exceptions](https://www.reddit.com/r/typescript/comments/1ka0ts5/a_better-way-to-handle-exceptions/)
|
|
940
|
-
- [Advanced Error Handling in TypeScript: Best Practices and Common Pitfalls](https://overctrl.com/advanced-error-handling-in-typescript-best-practices-and-common-pitfalls/)
|
|
941
|
-
- [The 5 commandments of clean error handling in TypeScript](https://backstage.orus.eu/the-5-commandments-of-clean-error-handling-in-typescript/)
|
|
942
|
-
- [How to Efficiently Handle Errors in TypeScript](https://dev.to/info_generalhazedawn_a3d/how-to-efficiently-handle-errors-in-typescript-3gf8)
|
|
943
|
-
- [Best Practices for Client-Side Logging and Error Handling in React](https://www.loggly.com/blog/best-practices-for-client-side-logging-and-error-handling-in-react/)
|
|
944
|
-
|
|
945
|
-
---
|
|
946
|
-
|
|
947
|
-
**End of Research Report**
|
|
948
|
-
|
|
949
|
-
**File:** `/home/dustin/projects/groundswell/plan_bugfix/P1M1T1S3/research/typescript_patterns.md`
|