0 day streak
javascript / expert
Snippet

Functional Error Handling with Result Monads

By replacing traditional try-catch blocks with a Result type, you enforce exhaustive error checking at compile time. This pattern is especially useful in Next.js Server Actions to ensure that all failure modes are explicitly handled before sending a response back to the client.

snippet.js
javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
type Result<T, E = Error> = { ok: true; value: T } | { ok: false; error: E };
async function safeFetchUser(id: string): Promise<Result<User>> {
try {
const user = await db.users.findUnique({ where: { id } });
if (!user) return { ok: false, error: new Error('User not found') };
return { ok: true, value: user };
} catch (e) {
return { ok: false, error: e as Error };
}
}
const response = await safeFetchUser('123');
if (response.ok) { console.log(response.value); }
nextjs
Breakdown
1
type Result<T, E = Error> = ...
Defines a union type representing either a successful computation or a failure.
2
if (!user) return { ok: false, error: ... };
Explicitly returns an error state instead of throwing, making the failure part of the API contract.
3
if (response.ok) { ... }
Uses TypeScript's type narrowing to safely access the value only when the operation succeeded.