Error handling consistente é sinal de maturidade no código. Aqui estão padrões que funcionam em qualquer linguagem.
Result Type (Either)
Em vez de lançar exceções, retorne um tipo que representa sucesso ou falha:
type Result<T, E = Error> =
| { ok: true; data: T }
| { ok: false; error: E };
async function fetchData(): Promise<Result<User>> {
try {
const res = await fetch("/api/user");
if (!res.ok) return { ok: false, error: new Error("HTTP Error") };
return { ok: true, data: await res.json() };
} catch (e) {
return { ok: false, error: e };
}
}
// Uso
const result = await fetchData();
if (!result.ok) return showError(result.error);
render(result.data);
Error Boundary (React)
Para UI que não pode quebrar:
class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError() {
return { hasError: true };
}
render() {
return this.state.hasError
? <Fallback />
: this.props.children;
}
}
Log estruturado
Nunca console.log(error). Prefira:
logger.error({
message: "Failed to fetch user",
userId: id,
error: error.message,
stack: error.stack,
});
Erro não tratado é dívida técnica com juros compostos. Um
catchvazio ou umconsole.errorsem contexto é pior que não capturar.