Releases: caiolandgraf/result-pattern
🚀 Result Pattern v2.3.2 - Elevating Error Handling with valueOrError, match, and Chaining!
✨ What's New in Result Pattern
This release introduces powerful new features that make working with the Result Pattern even more intuitive:
🎁 valueOrError() - Simplified Access to Values and Errors (Old unwrapOrGetErrors)
// Before: You had to handle Ok and Fail cases separately
if (result.isOk) {
const value = result.value;
// Use value
} else {
const error = result.value;
// Handle error
}
// Now: Get either the value or the error in one call!
const valueOrError = result.valueOrError();
// If result is Ok, valueOrError contains the success value
// If result is Fail, valueOrError contains the error valueThis method is especially powerful when working with error handling:
const userId = getUserId(); // May be invalid
const result = getUser(userId);
// Get either the user or the error message directly
console.log(`Result: ${result.valueOrError()}`);
// If successful: "Result: {id: 123, name: 'Caio'}"
// If failed: "Result: Invalid user ID"🎮 Elegant Pattern Matching with match
Another powerful feature is the match method, allowing elegant handling of both success and failure cases:
// Traditional approach with if/else
let message;
if (result.isOk) {
message = `Welcome, ${result.value.name}!`;
} else {
message = `Error: ${result.value}`;
}
// Now with pattern matching
const message = result.match({
ok: user => `Welcome, ${user.name}!`,
fail: error => `Error: ${error}`
});🔄 Enhanced Flow Control with andThen and orElse
The andThen and orElse methods provide elegant ways to chain operations based on result status:
// andThen executes only if the result is Ok
const result = validateUser(user)
.andThen(() => saveUser(user)) // Only runs if validation passes
.andThen(() => sendWelcomeEmail(user)); // Only runs if save succeeds
// orElse provides fallback behavior when a result is Fail
const userData = primaryDataSource.getUser(id)
.orElse(() => backupDataSource.getUser(id)) // Try backup if primary fails
.orElse(() => createDefaultUser(id)); // Create default as last resort🔍 Why These Methods Matter
These methods solve common pain points when working with the Result Pattern:
- ✅
valueOrError: Simplified access to either success values or error values - ✅
match: Declarative, pattern-based handling of both success and failure cases - ✅
andThen: Cleaner composition of operations that depend on previous success - ✅
orElse: Elegant fallback strategies without complex conditional logic
📋 Complete Feature List
This release builds on our solid foundation:
- ✅ Type-safe error handling with
Ok<V, E>andFail<V, E>classes - ✅ Powerful transformation methods like
map,flatMap, andmapFails - ✅ Error aggregation with
ResultUtils.combine - ✅ Flexible value extraction with
unwrap,unwrapOr, andunwrapOrElse - ✅ Value/error swapping with
flip - ✅ Direct value/error access with
valueOrError - ✅ Elegant pattern matching with
match - ✅ Enhanced flow control with
and,andThen,or, andorElse
🛠️ Migration Guide
This is a minor release with full backward compatibility. Simply update your package:
# npm
npm update @eicode/result-pattern
# yarn
yarn upgrade @eicode/result-pattern
# pnpm
pnpm update @eicode/result-pattern
📚 Usage Examples
Comprehensive Error Handling with Pattern Matching
function processPayment(paymentDetails) {
return validatePaymentDetails(paymentDetails)
.flatMap(details => processTransaction(details))
.match({
ok: receipt => ({
success: true,
receipt,
message: "Payment processed successfully!"
}),
fail: errors => ({
success: false,
errors,
message: "Payment processing failed"
})
});
}Complex Operations with andThen and orElse
function getUserData(userId: string): Result<UserData, string> {
return authenticateRequest()
.andThen(() => checkUserPermissions(userId))
.andThen(() => fetchUserFromPrimaryDB(userId))
.orElse(() => fetchUserFromBackupDB(userId))
.map(user => enrichUserData(user));
}
// Handle the result with valueOrError
const result = await getUserData("user-123");
const userOrError = result.valueOrError();
if (result.isOk) {
renderUserProfile(userOrError);
} else {
displayError(`Failed to load user: ${userOrError}`);
}Form Validation with Combined Results
function validateForm(formData) {
const name = validateName(formData.name);
const email = validateEmail(formData.email);
const password = validatePassword(formData.password);
// Combine all validations to get all errors at once
return ResultUtils.combine(name, email, password)
.match({
ok: ([validName, validEmail, validPassword]) => {
return {
success: true,
data: { name: validName, email: validEmail, password: validPassword }
};
},
fail: errors => {
return {
success: false,
errors
};
}
});
}Made with 💻, ☕, and a bit of 🪄 by @caiolandgraf and @JuniorBecari10
🚀 Result Pattern v2.2.0 - Introducing unwrapOrGetErrors()
✨ What's New
This release introduces a powerful new method that makes working with errors even more convenient:
🎁 unwrapOrGetErrors() - The Best of Both Worlds
// Before: You had to handle Ok and Fail cases separately
if (result.isOk) {
const value = result.value;
// Use value
} else {
const error = result.value;
// Handle error
}
// Now: Get either the value or the error in one call!
const valueOrError = result.unwrapOrGetErrors();
// If result is Ok, valueOrError contains the success value
// If result is Fail, valueOrError contains the error valueThis method is especially powerful when working with combined results:
const email = Email.try("user@example.com");
const password = StrongPassword.try("weak123");
const combined = ResultUtils.combine(email, password);
// Get either the valid data or all validation errors at once
console.log(combined.unwrapOrGetErrors());
// If validation fails: ["Password too weak"]
// If validation passes: [Email, StrongPassword]🔍 Why This Matters
The new unwrapOrGetErrors() method solves a common pain point when working with the Result Pattern:
- ✅ No more type constraints when you just want to access error values
- ✅ Cleaner code with fewer conditional branches
- ✅ Simplified error handling in combined results
- ✅ Better developer experience with less boilerplate
📋 Complete Feature List
This release builds on our solid foundation:
- ✅ Type-safe error handling with
Ok<V, E>andFail<V, E>classes - ✅ Powerful transformation methods like
map,flatMap, andmapFails - ✅ Error aggregation with
ResultUtils.combine - ✅ Flexible value extraction with
unwrap,unwrapOr, andunwrapOrElse - ✅ Logical operations with
andandormethods - ✅ Value/error swapping with
flip - ✅ NEW: Direct error access with
unwrapOrGetErrors
🛠️ Migration Guide
This is a minor release with full backward compatibility. Simply update your package:
# npm
npm update @eicode/result-pattern
# yarn
yarn upgrade @eicode/result-pattern
# pnpm
pnpm update @eicode/result-pattern
Then start using the new unwrapOrGetErrors() method wherever you need to access either success values or error values without type constraints.
📚 Usage Examples
Form Validation
function validateForm(formData: FormData) {
const name = validateName(formData.get('name'));
const email = validateEmail(formData.get('email'));
const password = validatePassword(formData.get('password'));
const result = ResultUtils.combine(name, email, password);
// Get either the validated data or all validation errors
const dataOrErrors = result.unwrapOrGetErrors();
if (result.isFail) {
// dataOrErrors is an array of error messages
displayErrors(dataOrErrors);
} else {
// dataOrErrors is a tuple of validated values
submitForm(dataOrErrors);
}
}API Request Handling
async function fetchUserData(userId: string) {
try {
const response = await fetch(`/api/users/${userId}`);
if (!response.ok) {
return new Fail(`HTTP error: ${response.status}`);
}
const data = await response.json();
return new Ok(data);
} catch (error) {
return new Fail(`Network error: ${error.message}`);
}
}
// In your component:
const userData = await fetchUserData(userId);
const userOrError = userData.unwrapOrGetErrors();
if (userData.isOk) {
renderUserProfile(userOrError);
} else {
showErrorMessage(userOrError);
}Made with 💻, ☕, and a bit of 🪄 by @caiolandgraf
Robust Error Handling & Smarter Result Composition ⚡
🚀 New Additions:
✅ 📌 Introduced Ok and Fail result classes for more structured error handling.
✅ 🛠️ Added a generic IResult interface with methods to handle both success and failure results.
✅ 🌀 Enhanced methods like map, flatMap, mapFails, flip for better chaining and error propagation.
✅ ⚡ New utilities like unwrapOrElse and unwrapOr for handling fallbacks.
✅ 🔄 Expanded the combine utility for combining multiple results with error propagation.
Differences between versions
-
Types:
- v2.0.0: The
Resulttype defines the generic parameters<V, E>, whileOkandFailclasses are more explicit with defaults (V = never,E = never). - v2.1.0: The
Resulttype uses default values (V = unknown,E = unknown) for more flexibility.
- v2.0.0: The
-
Method Implementations:
- v2.0.0: Methods like
map,flatMap,unwrapOrElseare more streamlined and return the same type (OkorFail) for chaining without much type manipulation. - v2.1.0: The
mapFailsmethod is more precise in how it deals with failures, clearly transforming errors and allowing for stronger type safety.
- v2.0.0: Methods like
-
Combine Utility:
- v2.0.0: The
combinefunction ensures that errors are aggregated by collecting them from allFailresults and returns a singleFailcontaining all error values. - v2.1.0: The
combinefunction is slightly modified to ensure it handles emptyFailvalues more effectively and uses theunwrapOrmethod to extract values in theOkcase.
- v2.0.0: The
-
Error Propagation:
- v2.0.0: Focuses on a simpler structure where the
unwrapfunction throws an error if called on aFail. - v2.1.0: Adds more functionality to handle fallback values (
unwrapOr,unwrapOrElse), improving error recovery flexibility.
- v2.0.0: Focuses on a simpler structure where the
Made with 💻, ☕, and a bit of 🪄 by @caiolandgraf
Enhanced Error Handling & Safe Data Flow 🚀
🚀 New Additions:
✅ 📌 API response handling using Result for safe data retrieval.
✅ 🛠️ Form validation example, combining multiple Result instances.
✅ 🌀 Transformation pipelines demonstrating map, flatMap, and unwrapOrElse.
✅ ⚡ Nested Result handling for more complex cases.
✅ 🔄 Fallback mechanisms using unwrapOrElse.
✅ 🛑 Error propagation and handling via mapFails.
Made with 💻, ☕, and a bit of 🪄 by @caiolandgraf