Result Type Over Throw
Functions that have expected failure modes (network errors, validation failures, not-found) should return a `Result<T, E>` discriminated union rather than throwing exceptions.…
$ aoe install @team/pattern-result-type-over-throw Projection
Always in _index.xml · the agent never has to ask for this.
ResultTypeOverThrow [pattern] v1.0.0
Functions that have expected failure modes (network errors, validation failures, not-found) should return a Result<T, E> discriminated union rather than throwing exceptions. Exceptions are for unexpected, unrecoverable failures only.
Loaded when retrieval picks the atom as adjacent / supporting.
ResultTypeOverThrow [pattern] v1.0.0
Functions that have expected failure modes (network errors, validation failures, not-found) should return a Result<T, E> discriminated union rather than throwing exceptions. Exceptions are for unexpected, unrecoverable failures only.
Label
Result<T, E> over throw for expected errors
Problem
Thrown exceptions are invisible in the function signature — a caller reading fetchUser(id) has no indication it might throw. The compiler cannot enforce that all call sites handle the error. Error handling is ad-hoc and easy to forget.
Solution
type Result<T, E = Error> =
| { ok: true; value: T }
| { ok: false; error: E };
// Function signature makes failure explicit:
async function fetchUser(id: string): Promise<Result<User, 'not-found' | 'network-error'>> {
try {
const user = await db.users.findById(id);
if (!user) return { ok: false, error: 'not-found' };
return { ok: true, value: user };
} catch {
return { ok: false, error: 'network-error' };
}
}
// Caller is forced to handle both branches:
const result = await fetchUser(id);
if (!result.ok) {
if (result.error === 'not-found') return notFoundResponse();
return internalError();
}
return result.value;
Loaded when retrieval picks the atom as a focal / direct hit.
ResultTypeOverThrow [pattern] v1.0.0
Functions that have expected failure modes (network errors, validation failures, not-found) should return a Result<T, E> discriminated union rather than throwing exceptions. Exceptions are for unexpected, unrecoverable failures only.
Label
Result<T, E> over throw for expected errors
Problem
Thrown exceptions are invisible in the function signature — a caller reading fetchUser(id) has no indication it might throw. The compiler cannot enforce that all call sites handle the error. Error handling is ad-hoc and easy to forget.
Solution
type Result<T, E = Error> =
| { ok: true; value: T }
| { ok: false; error: E };
// Function signature makes failure explicit:
async function fetchUser(id: string): Promise<Result<User, 'not-found' | 'network-error'>> {
try {
const user = await db.users.findById(id);
if (!user) return { ok: false, error: 'not-found' };
return { ok: true, value: user };
} catch {
return { ok: false, error: 'network-error' };
}
}
// Caller is forced to handle both branches:
const result = await fetchUser(id);
if (!result.ok) {
if (result.error === 'not-found') return notFoundResponse();
return internalError();
}
return result.value;
Relations
related: [@team/rule-explicit-return-types, @team/tradeoff-strict-types-vs-iteration-speed, @team/anti-pattern-god-class] enhances: [@team/rule-explicit-return-types]
Label
Result<T, E> over throw for expected errors
Problem
Thrown exceptions are invisible in the function signature — a caller reading fetchUser(id) has no indication it might throw. The compiler cannot enforce that all call sites handle the error. Error handling is ad-hoc and easy to forget.
Solution
type Result<T, E = Error> =
| { ok: true; value: T }
| { ok: false; error: E };
// Function signature makes failure explicit:
async function fetchUser(id: string): Promise<Result<User, 'not-found' | 'network-error'>> {
try {
const user = await db.users.findById(id);
if (!user) return { ok: false, error: 'not-found' };
return { ok: true, value: user };
} catch {
return { ok: false, error: 'network-error' };
}
}
// Caller is forced to handle both branches:
const result = await fetchUser(id);
if (!result.ok) {
if (result.error === 'not-found') return notFoundResponse();
return internalError();
}
return result.value;
Enhances
- @team/rule-explicit-return-types
Source
aoe-engine/examples/coding-style/primes/compiled/@team/pattern-result-type-over-throw/atom.yaml