DeesseJS FP

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; // None

maybe

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/undefined

Transformation

map

Transforms the value if Some, passes through if None.

some(5).map((n) => n * 2); // Some(10)
none.map((n) => n * 2); // None

flatMap (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)); // None

filter

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); // None

filterMap

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)); // None

tap

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
); // 10

Unwrapping

getOrElse

Returns the value or a fallback.

some(5).getOrElse(0); // 5
none.getOrElse(0); // 0

getOrNull

Returns the value or null.

some(5).getOrNull(); // 5
none.getOrNull(); // null

getOrUndefined

Returns the value or undefined.

some(5).getOrUndefined(); // 5
none.getOrUndefined(); // undefined

getOrThrow

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 type

This 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 default

Conversion

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>>; // string

isMaybe

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

See Also

On this page