What this prompt does
This prompt designs a type-safe error handling architecture for a TypeScript [app_type]. It asks for a Result<T, E> monad to replace try/catch, a custom error hierarchy ([error_classes]), an error-code enum with HTTP status mapping, centralized middleware that formats responses as [error_format], async error boundaries, domain error factories, safe serialization for logging, discriminated-union narrowing, error aggregation for batch operations, and tests verifying types, messages, and status codes.
The structure works because scattered try/catch is where production bugs hide: swallowed errors, leaked internals, inconsistent status codes. By centralizing formatting to [error_format] (RFC 7807 by default) and demanding a before/after comparison, the output makes the shift from ad-hoc handling to typed, predictable error contracts explicit. The serialization rule — full stack and context to logs, nothing internal to clients — is the security-relevant part that the prompt bakes in deliberately.
When to use it
- When a TypeScript
[app_type]has try/catch scattered everywhere and inconsistent errors - When API error responses need to follow a standard like
[error_format] - When you want compile-time guarantees that callers handle error cases
- When error responses risk leaking stack traces or internal details to clients
- When batch operations must collect all errors instead of failing on the first
- When mapping the
[error_classes]hierarchy to consistent HTTP status codes - When you want compile-time exhaustiveness so adding a new error variant forces every caller to handle it
Example output
Expect a TypeScript design: a Result<T, E> implementation, the [error_classes] hierarchy, an error-code enum with HTTP status and user-friendly message mapping, the centralized middleware emitting [error_format], async error boundaries that wrap operations automatically, domain error factories with a fluent builder, logging serialization that includes stack, context, and request ID without leaking internals, and tests asserting status and type. Discriminated-union narrowing lets the compiler force every branch to be handled, and the batch aggregation collects all errors instead of failing on the first. The prompt also produces a side-by-side before/after showing try/catch spaghetti versus the Result-based approach, which makes the migration concrete rather than theoretical.
Pro tips
- List your real
[error_classes]so the hierarchy and status mapping match your domain rather than generic categories - Keep
[error_format]as RFC 7807 unless a client contract requires otherwise; standard problem details save integrators effort - Verify the serialization rule holds: full stack and request ID to logs, never to the client response body
- Use the discriminated-union narrowing so the compiler forces every error branch to be handled instead of silently dropped
- For batch flows, lean on the aggregation feature so one bad record does not abort the whole operation
- Treat the Result monad as a gradual migration — wrap new code first rather than rewriting every existing try/catch at once