Result
Ok | Err for type-safe error handling
Result represents a value that may have failed. It has two variants: Ok for success and Err for failure. This makes error handling explicit and type-safe — no more forgotten try/catch blocks.
Why Result?
Instead of throwing exceptions, functions return Result. Errors become values you can transform, chain, and handle just like any other data.
// Without Result - exceptions can slip through
function parseJSON(input: string) {
return JSON.parse(input); // throws on invalid input
}
// With Result - errors are part of the type
function parseJSON(input: string) {
try {
return ok(JSON.parse(input));
} catch (e) {
return err(e as Error);
}
}Constructors
ok
Creates a successful Result.
import { ok } from '@deessejs/fp';
ok(5); // Ok<number, never>
ok('hello'); // Ok<string, never>
ok({ id: 1 }); // Ok<{ id: number }, never>err
Creates a failed Result.
import { err } from '@deessejs/fp';
err('Something went wrong'); // Err<never, string>
err(new Error('Database error')); // Err<never, Error>Transformation
map
Transforms the value if Ok, passes through if Err.
ok(5).map((n) => n * 2); // Ok(10)
err('oops').map((n) => n * 2); // Err('oops')flatMap (chain)
Chains a Result-returning function on success. Short-circuits on Err.
ok(5).flatMap((n) => ok(n * 2)); // Ok(10)
ok(5).flatMap((n) => err('bad')); // Err('bad')
err('oops').flatMap((n) => ok(n * 2)); // Err('oops')mapError
Transforms the error if Err, passes through if Ok.
ok(5).mapError((e) => new Error(e)); // Ok(5)
err('bad').mapError((e) => new Error(e)); // Err(Error('bad'))filter
Returns Ok if the predicate passes. When the predicate fails, behaviour depends on whether errorFn is supplied:
- With
errorFn: returnsErr(errorFn(value)). - Without
errorFn: passes throughOk(value)unchanged (useful for "pass-through" filtering without changing the type).
Err.filter always passes through.
ok(4).filter((n) => n % 2 === 0); // Ok(4) — predicate passes
ok(3).filter((n) => n % 2 === 0); // Ok(3) — predicate fails, no errorFn, pass-through
ok(3).filter(
(n) => n % 2 === 0,
(n) => `odd:${n}`
); // Err('odd:3') — errorFn invoked
err('bad').filter((n) => n > 0); // Err('bad') — passes throughtap
Runs a side effect on Ok, returns the original Result unchanged.
ok(5)
.tap((n) => console.log('Value:', n)) // logs 'Value: 5'
.map((n) => n * 2); // Ok(10)tapAsync
Async version of tap. Runs the async function and returns the original Result.
await ok(5).tapAsync(async (n) => {
await sendAnalytics('value_received', { value: n });
});flatMapAsync
Chains an async Result-returning function.
async function fetchUser(id: string) {
return ok({ id, name: 'Alice' });
}
await ok('123').flatMapAsync(fetchUser); // Promise<Ok<{ id: string, name: string }, never>>Pattern Matching
match
Transforms both variants to the same type.
ok(5).match({
ok: (value) => `Success: ${value}`,
err: (error) => `Error: ${error}`,
}); // 'Success: 5'fold
Alias for match. Transforms both variants to the same type.
ok(5).fold(
(value) => value * 2,
(error) => 0
); // 10Unwrapping
getOrElse
Returns the value or a fallback.
ok(5).getOrElse(0); // 5
err('oops').getOrElse(0); // 0getOrNull
Returns the value or null.
ok(5).getOrNull(); // 5
err('oops').getOrNull(); // nullgetOrUndefined
Returns the value or undefined.
ok(5).getOrUndefined(); // 5
err('oops').getOrUndefined(); // undefinedgetOrThrow
Returns the value or throws the error.
ok(5).getOrThrow(); // 5
err('oops').getOrThrow(); // throws Error('oops')
err(new Error('bad')).getOrThrow(); // throws Error('bad')Type Guards
isOk
Type guard that narrows to Ok.
const result = ok(5);
if (result.isOk()) {
result.value; // number — TypeScript knows it's Ok
}isErr
Type guard that narrows to Err.
const result = err('oops');
if (result.isErr()) {
result.error; // string — TypeScript knows it's Err
}Conversion
toMaybe
Converts Ok to Some and Err to None.
ok(5).toMaybe(); // Some(5)
err('oops').toMaybe(); // NoneType Utilities
OkType
Extracts the Ok type from a Result.
import type { OkType } from '@deessejs/fp';
type T = OkType<Result<string, Error>>; // stringErrType
Extracts the Err type from a Result.
import type { ErrType } from '@deessejs/fp';
type E = ErrType<Result<string, Error>>; // ErrorisResult
Type guard to check if a value is a Result.
import { isResult } from '@deessejs/fp';
isResult(ok(5)); // true
isResult(err('bad')); // true
isResult('hello'); // false