Error Handling
Building reliable apps isn't just about making things work. It’s about making sure things fail gracefully when they don’t. That’s where Effect comes in — a modern, composable effect system for TypeScript and JavaScript — aligning with Zap.ts' philosophy.
Why use Effect?
Most people sprinkle try/catch
or .catch()
throughout their code — and it works… until it doesn’t. You end up with inconsistent error handling, unreadable logic, and debugging nightmares.
Effect fixes that by giving you:
- Better testability — effects are easy to simulate/mock
- Composable workflows — you can chain logic clearly
- Explicit error handling — no hidden surprises
- Type-safe async code — TypeScript actually helps you
Instead of letting errors blow up in random places, you model them as data. That makes your app’s behavior predictable and easier to reason about.
A simple example
Here’s how you’d wrap an async API call using Effect.tryPromise
, it's pretty similar to what you already know.
import { Effect } from "effect";
const fetchUser = (id: string) =>
Effect.tryPromise({
try: async () => {
const res = await fetch(`/api/users/${id}`);
if (!res.ok) throw new Error("User not found");
return res.json();
},
catch: (err) => err,
});
Effect.runPromise(fetchUser("123"))
.then((user) => {
// handle user
})
.catch((error) => {
// handle error
});
Effect.tryPromise
lets you safely run async code without random crashes. Everything is contained and type-checked.
Handling Errors Declaratively
You can also cleanly handle errors as part of your logic, without nested .then()
s or try/catch
blocks. Here’s how:
import { Effect } from "effect";
const safeFetch = fetchUser("123").pipe(
Effect.catchAll((error) => Effect.succeed({ error }))
);
Effect.runPromise(safeFetch).then((result) => {
if ("error" in result) {
// handle error
} else {
// handle success
}
});
What’s happening here? Let's try to understand the above code.
- You try to fetch the user.
- If it fails, you catch the error and return it as a regular value.
- Now everything — success and failure — is part of the same flow.
- No surprises, no runtime crashes.
Learn More
We recommend you to check the Effect Documentation to learn more. While it can be a mind shift, once you get it, your code will be way more predictable.