Skip to content

Result Pattern

The Result pattern is a clean, type-safe way to handle success or failure in operations without throwing exceptions.

✅ Prevents uncontrolled exceptions from leaking into your application.
✅ Makes function return types clear and predictable.


Instead of returning raw values or throwing errors, you wrap the outcome in a Result object.

This object has:

  • A success/failure status.
  • Either the successful result or the failure reason.

Example:

const result = await service.doSomething();
if (result.isSuccess()) {
const value = result.value;
} else {
const error = result.error;
}

✅ This forces the caller to explicitly handle both success and error cases.


DomusJS provides the following:

export class Result<T, E> {
isSuccess(): boolean;
isFailure(): boolean;
value: T;
error: E;
}
Result.ok(value);
Result.fail(error);
const result = Result.ok('User created');
if (result.isSuccess()) {
console.log(result.value); // 'User created'
}

import { Result } from '@domusjs/core';
export async function registerUser(email, password): Promise<Result<User, string>> {
if (await userExists(email)) {
return Result.fail('Email already taken');
}
const user = await createUser(email, password);
return Result.ok(user);
}
const result = await registerUser('test@example.com', 'password123');
if (result.isSuccess()) {
console.log('User registered:', result.value);
} else {
console.error('Failed to register user:', result.error);
}

✅ This makes sure no uncaught exceptions happen.


✅ Use Result to wrap operations where failure is a normal, expected possibility.
✅ Avoid using it for critical, unexpected failures (those should be proper exceptions).
✅ Always handle both paths (ok and fail) at the call site.


  • Clearer code: success and error cases are always visible.
  • Safer APIs: avoids forgotten .catch() blocks or missed error branches.
  • Easier testing: you can easily test both successful and failing scenarios.