Const
Readonly
ok: <ResultType, ErrorType extends Error = Error>(Creates a successful Result containing the provided value. The value can be of any type, including null and undefined.
const stringValue = result.ok("Hello");
const numberValue = result.ok(42);
const objectValue = result.ok({ name: "John", age: 30 });
const nullValue = result.ok(null);
const undefinedValue = result.ok(undefined);
// All of these are Ok Results
console.log(stringValue.is_ok()); // true
console.log(numberValue.value_or(0)); // 42
Readonly
error: <ResultType, ErrorType extends Error = Error>(Creates a failed Result containing the provided error. The error must be an instance of Error or a subclass of Error.
const basicError = result.error(new Error("Basic error"));
const typeError = result.error<string, TypeError>(new TypeError("Wrong type"));
const customError = result.error(new RangeError("Out of range"));
// Explicitly typed error results
const parseError: Result<number, Error> = result.error<number, Error>(new Error("Parse failed"));
const validationError = result.error<User, ValidationError>(new ValidationError("Invalid data"));
// All of these are Error Results
console.log(basicError.is_error()); // true
if (typeError.is_error()) {
console.log(typeError.error.message); // "Wrong type"
}
// Custom error classes work too
class ValidationError extends Error {
field: string;
constructor(message: string, field: string) {
super(message);
this.name = "ValidationError";
this.field = field;
}
}
Readonly
try: <T>(fn: () => T) => Result<T, Error>Executes a function and wraps the result in a Result type. If the function executes successfully, returns an Ok Result with the return value. If the function throws an error, returns an Error Result with the caught error.
// Working with a function that might throw
function parseJSON(jsonString: string): any {
return JSON.parse(jsonString); // Throws SyntaxError for invalid JSON
}
const validResult = result.try(() => parseJSON('{"name": "John"}'));
if (validResult.is_ok()) {
console.log(validResult.value.name); // "John"
}
const invalidResult = result.try(() => parseJSON('invalid json'));
if (invalidResult.is_error()) {
console.log(invalidResult.error.message); // "Unexpected token i in JSON at position 0"
}
// Converting existing throwing APIs
const fileContent = result.try(() => fs.readFileSync('file.txt', 'utf8'));
const parsedNumber = result.try(() => {
const num = parseInt(userInput);
if (isNaN(num)) throw new Error("Not a valid number");
return num;
});
Readonly
try_async: <T>(fn: () => Promise<T>) => AsyncResult<T, Error>Executes an async function and wraps the result in an AsyncResult
.
The AsyncResult
is a PromiseLike
that supports the Result method chaining interfaces,
and it can be await
ed to access the Result
and its contained value or error.
If the function resolves successfully, the AsyncResult will contain an Ok Result with the resolved value.
If the function rejects or throws, the AsyncResult will contain an Error Result with the caught error.
To access the final Result
, you will need to first await
the AsyncResult
.
// Immediate chaining without intermediate awaits
const processedUser = result.try_async(() => fetchUserData("123"))
.map(user => ({ ...user, name: user.name.toUpperCase() }))
.and_then(user => user.name ? result.ok(user) : result.error(new Error("Invalid name")))
.or_else(() => result.ok(createDefaultUser()));
// Only await when you need the final result
const finalUser = await processedUser;
if (finalUser.is_ok()) {
console.log("Processed user:", finalUser.value.name);
}
// Converting Promise-based APIs with chaining
const fileData = await result.try_async(() => fs.promises.readFile('file.txt', 'utf8'))
.map(content => content.trim())
.and_then(content => content.length > 0 ? result.ok(content) : result.error(new Error("Empty file")));
Readonly
retry: <ValueType, ErrorType extends Error>(Retries a result-returning function until it succeeds or has failed for all of the requested retries. If the function returns an Ok Result, the retry operation stops and returns that successful Result. If the function returns an Error Result, it's retried up to the specified number of times. If all retries fail, returns an Error Result containing all the accumulated errors.
let attempts = 0;
function unreliableOperation(): Result<string, Error> {
attempts++;
if (attempts < 3) {
return result.error(new Error(`Attempt ${attempts} failed`));
}
return result.ok("Success!");
}
const retryResult = result.retry(unreliableOperation, 5);
if (retryResult.is_ok()) {
console.log(retryResult.value); // "Success!"
}
// Network request example
function fetchData(): Result<string, Error> {
// Simulated network request that might fail
return Math.random() > 0.7
? result.ok("Data fetched successfully")
: result.error(new Error("Network timeout"));
}
const networkResult = result.retry(fetchData, 3);
networkResult.match({
on_ok: (data) => console.log("Got data:", data),
on_error: (error) => console.log("All retries failed:", error.errors.map(e => e.message))
});
// Can be chained with other Result operations
const processedResult = result.retry(fetchData, 3)
.map(data => data.toUpperCase())
.and_then(data => data.includes("SUCCESS") ? result.ok(data) : result.error(new Error("Invalid data")));
Readonly
retry_async: <ValueType, ErrorType extends Error>(Retries a Promise
let attempts = 0;
async function unreliableAsyncOperation(): Promise<Result<string, Error>> {
attempts++;
await new Promise(resolve => setTimeout(resolve, 100)); // Simulate async work
if (attempts < 3) {
return result.error(new Error(`Async attempt ${attempts} failed`));
}
return result.ok("Async success!");
}
const retryResult = await result.retry_async(unreliableAsyncOperation, 5);
if (retryResult.is_ok()) {
console.log(retryResult.value); // "Async success!"
}
// Network request example
async function fetchDataAsync(): Promise<Result<string, Error>> {
return result.try_async(async () => {
const response = await fetch('/api/data');
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const data = await response.text();
return result.ok(data);
})
}
const networkResult = await result.retry_async(fetchDataAsync, 3);
networkResult.match({
on_ok: (data) => console.log("Got data:", data),
on_error: (error) => console.log("All retries failed:", error.errors.map(e => e.message))
});
// Can be chained with other Result operations
const processedResult = await result.retry_async(fetchDataAsync, 3)
.then(res => res.map(data => data.toUpperCase()))
.then(res => res.and_then(data =>
data.includes("SUCCESS") ? result.ok(data) : result.error(new Error("Invalid data"))
));
import { result, type Result } from "./result.ts";
// Creating success results
const success = result.ok("Hello, World!");
const number = result.ok(42);
const nullValue = result.ok(null);
// Creating error results
const failure = result.error(new Error("Something went wrong"));
const customError = result.error(new TypeError("Type mismatch"));
// Chaining operations
const processed = result.ok(" hello ")
.map(str => str.trim())
.map(str => str.toUpperCase())
.and_then(str => str.length > 0 ? result.ok(str) : result.error(new Error("Empty string")));
Factory functions for creating Result instances. This module provides the primary API for constructing Result values.