Maybe
Some | None for optional values
Maybe represents a value that may or may not exist. It has two variants: Some for present values and None for absent values. This makes optional values explicit and safe — no more undefined is not a function.
Why Maybe?
No more null checks that silently pass or crash at runtime. Maybe makes absence a first-class concept.
// Without Maybe — crashes if user is undefined
const name = users.find(u => u.id === id).profile.displayName;
// With Maybe — safe and explicit
const name = maybe(users.find(u => u.id === id))
.flatMap(u => maybe(u.profile))
.map(p => p.displayName)
.getOrElse('Anonymous');Constructors
some
Creates a Some (present value).
import { some } from '@deessejs/fp';
some(5); // Some<number>
some('hello'); // Some<string>
some({ id: 1 }); // Some<{ id: number }>none
The None singleton (absent value).
import { none } from '@deessejs/fp';
none; // Nonemaybe
Creates Some from a non-null value, None from null or undefined.
import { maybe } from '@deessejs/fp';
maybe(5); // Some(5)
maybe(null); // None
maybe(undefined); // None
maybe(0); // Some(0) — 0 is not null/undefined
maybe(''); // Some('') — empty string is not null/undefinedTransformation
map
Transforms the value if Some, passes through if None.
some(5).map(n => n * 2); // Some(10)
none.map(n => n * 2); // NoneflatMap (chain)
Chains a Maybe-returning function. Short-circuits on None.
some(5).flatMap(n => some(n * 2)); // Some(10)
some(5).flatMap(() => none); // None
none.flatMap(n => some(n * 2)); // Nonefilter
Returns Some if the predicate passes, None if it fails.
some(4).filter(n => n % 2 === 0); // Some(4)
some(3).filter(n => n % 2 === 0); // None
none.filter(n => n > 0); // NonefilterMap
Chains a Maybe-returning function. Alias for flatMap.
some(5).filterMap(n => n > 0 ? some(n * 2) : none); // Some(10)
some(-1).filterMap(n => n > 0 ? some(n * 2) : none); // Nonetap
Runs a side effect on Some, returns the original Maybe unchanged.
some(5)
.tap(n => console.log('Value:', n)) // logs 'Value: 5'
.map(n => n * 2); // Some(10)tapAsync
Async version of tap.
await some(5).tapAsync(async n => {
await sendAnalytics('received', { value: n });
});Pattern Matching
match
Transforms both variants to the same type.
some(5).match({
some: (value) => `Got ${value}`,
none: () => 'Nothing',
}); // 'Got 5'fold
Alias for match. Transforms both variants to the same type.
some(5).fold(
(value) => value * 2,
() => 0,
); // 10Unwrapping
getOrElse
Returns the value or a fallback.
some(5).getOrElse(0); // 5
none.getOrElse(0); // 0getOrNull
Returns the value or null.
some(5).getOrNull(); // 5
none.getOrNull(); // nullgetOrUndefined
Returns the value or undefined.
some(5).getOrUndefined(); // 5
none.getOrUndefined(); // undefinedgetOrThrow
Returns the value or throws.
some(5).getOrThrow(); // 5
none.getOrThrow(); // throws Error('Expected Some but got None')Property Access
get
Safely accesses a property of the wrapped value. Returns Maybe for the property type.
const user = some({ name: 'Alice', address: { city: 'Paris' } });
user.get('name'); // Some('Alice')
user.get('address').get('city'); // Some('Paris')
user.get('email'); // None — property doesn't exist on typeThis is especially useful for chaining through nested objects.
some({ user: { profile: { avatar: 'url' } } })
.get('user')
.get('profile')
.get('avatar')
.getOrElse('/default.png'); // Returns the avatar or defaultConversion
toResult
Converts Some to Ok and None to Err with a provided error value.
some(5).toResult('not found'); // Ok(5)
none.toResult('not found'); // Err('not found')toArray
Converts to an array.
some(5).toArray(); // [5]
none.toArray(); // []toIterable
Converts to an Iterable.
[...some(5)]; // [5]
[...none]; // []Type Guards
isSome
Type guard that narrows to Some.
const maybe = some(5);
if (maybe.isSome()) {
maybe.value; // number — TypeScript knows it's Some
}isNone
Type guard that narrows to None.
const maybe = some(5);
if (maybe.isNone()) {
// unreachable here
}Type Utilities
SomeType
Extracts the inner type from a Maybe.
import type { SomeType } from '@deessejs/fp';
type T = SomeType<Maybe<string>>; // stringisMaybe
Type guard to check if a value is a Maybe.
import { isMaybe } from '@deessejs/fp';
isMaybe(some(5)); // true
isMaybe(none); // true
isMaybe(5); // false