Skip to content

Maybe

ts
type Maybe<A> = None | Some<A>

The Maybe is a container for an optional value, it represents missing values or the effect of a possibly failing computation. The Some data constructor is used for wrapping present values while the None constructor is used when a value is absent.

Example

Without Maybe

ts
const plusOne = (n?: number) => {
  if (n === undefined) return n

  return n + 1
}

const num2Str = (n?: number) => {
  if (n === undefined) return ''

  return String(v)
}

num2Str(plusOne(1)) // => '2'
num2Str(plusOne())  // => ''

With Maybe

ts
const f = flow(
  map((n: number) => n + 1),
  match(() => '', (n: number) => `${n}`),
)

f(some(1)) // => '2'
f(none)    // => ''

API

some

ts
<A>(value: A) => Maybe<A>

Constructs a Some. Represents an optional value that exists.

ts
some(1) ➔ { readonly _tag: 'Some', readonly value: A }

none

ts
Maybe<never>

None value. Represents a missing value.

ts
none ➔ { readonly _tag: 'None' }

isSome

ts
<A>(ma: Maybe<A>) => ma is Some<A>

Returns whether the Maybe is Some or not.

ts
isSome(some(1)) ➔ true
isSome(none)    ➔ false

isNone

ts
<A>(ma: Maybe<A>) => ma is None

Returns whether the Maybe is None or not.

ts
isNone(some(1)) ➔ false
isNone(none)    ➔ true

equals

ts
<A>(a: Maybe<A>, b: Maybe<A>) => boolean

Compares one Maybe to another Maybe. Returns false if maybes or the wrapped values are different.

ts
equals(some(1), some(1)) ➔ true
equals(some(2), some(1)) ➔ false
equals(some(1), none)    ➔ false
equals(none, none)       ➔ true
equals(none, right(1))   ➔ false

of

ts
<A>(value: A) => Maybe<A>

Takes a value and wraps it into a Some.

ts
of(1) ➔ some(1)

zero

ts
() => None

Alias of none.

empty

ts
() => None

Alias of none.

map

ts
<A, B>(f: (a: A) => B) => (fa: Maybe<A>) => Maybe<B>

Transforms the Maybe with a given function. Returns None if the Maybe is None.

ts
pipe(some(1), (n: number) => n + 1) ➔ some(2)
pipe(none, (n: number) => n + 1)    ➔ none

alt

ts
<B>(that: Lazy<Maybe<B>>) => <A>(ma: Maybe< A>): Maybe<A | B>

Returns the Maybe if it is Some, otherwise returns the function result.

ts
pipe(some(0), alt(() => some(1))) ➔ some(0)
pipe(none, alt(() => some(1)))    ➔ some(1)

ap

ts
<A>(ma: Maybe<A>) => <B>(fab: Maybe<(a: A) => B>) => Maybe<B>

Applies a Some function over a Some value. Returns None if the Maybe or the function is None.

ts
pipe(some((n: number) => n + 1), ap(some(1))) ➔ some(2)
pipe(none, ap(some(1)))                       ➔ none
pipe(some((n: number) => n + 1), ap(none))    ➔ none

filter

ts
<A>(predicate: Predicate<A>) => (ma: Maybe<A>) => Maybe<A>

Takes a predicate function and a Maybe, returns the Maybe if it's Some and the predicate returns true, otherwise returns None.

ts
const f = flow(filter((n: number) => n > 0))

f(some(1)) ➔ some(1)
f(some(0)) ➔ none
f(none)    ➔ none

match

ts
<B, A, C>(onNone: Lazy<B>, onSome: (a: A) => C) => (ma: Maybe<A>) => B | C

Returns the onNone default value if the Maybe is None, otherwise returns the onSome function result with Maybe.

ts
pipe(some(1), match(() => 0, (n: number) => n + 1)) ➔ 2
pipe(none, match(() => 0, (n: number) => n + 1))    ➔ 0

chain

ts
<A, B>(f: (a: A) => Maybe<B>) => (ma: Maybe<A>) => Maybe<B>

Composes computations in sequence. Useful for chaining many computations that may result in a missing value.

ts
pipe(some(1), chain((n: number) => n > 0 ? some(n) : none)) ➔ some(1)
pipe(some(0), chain((n: number) => n > 0 ? some(n) : none)) ➔ none
pipe(none, chain((n: number) => n > 0 ? some(n) : none))    ➔ none

extend

ts
<A, B>(f: (a: Maybe<A>) => B) => (ma: Maybe<A>) => Maybe<B>

Returns none if the Maybe is a None, otherwise returns the result of the applying function and wrapped in a Some.

ts
pipe(some(1), extend(getOrElse(zero))) ➔ some(1)
pipe(none, extend(getOrElse(zero))) ➔ none

filter

ts
<A>(predicate: Predicate<A>) => (ma: Maybe<A>) => Maybe<A>

Takes a predicate function and a Maybe, returns the Maybe if it's Some and the predicate returns true, otherwise returns None.

ts
pipe(some(1), filter((n: number) => n > 0)) ➔ some(1)
pipe(some(0), filter((n: number) => n > 0)) ➔ none
pipe(none, filter((n: number) => n > 0))    ➔ none

reduce

ts
<A, B>(f: (acc: B, a: A) => B, b: B) => (ma: Maybe<A>) => B

Takes a function and an initial value and returns the initial value if Maybe is none, otherwise returns the result of applying the function to the initial value and the value inside Maybe.

ts
pipe(some(1), reduce((acc, a) => acc + a, 1)) ➔ 2
pipe(none, reduce((acc, a) => acc + a, 1))    ➔ 1

traverse

ts
PipeableTraverse1<MaybeKind>

Maps each element of a HKT structure to an action, and collects the results wrapped in Some.

Returns a HKT contains a none if the Maybe is a None.

ts
const f = traverse(Maybe.Monad)((n: number) => n > 0 ? some(n): none)
pipe(some(1), f)  ➔ some(some(1))
pipe(none, f)     ➔ some(none)
pipe(some(-1), f) ➔ none

getOrElse

ts
<A>(onNone: Lazy<A>) => <B>(ma: Maybe<B>) => A | B

Extracts the value of `Maybe , otherwise returns then default onNone value.

ts
pipe(some(1), getOrElse(() => 0)) ➔ 1
pipe(none, getOrElse(() => 0))    ➔ 0

orElse

ts
<B>(onNone: Lazy<Maybe<B>>) => <A>(ma: Maybe<A>) => Maybe<B | A>

Returns Maybe if it's a Some, otherwise returns onNone result.

ts
pipe(some(1), orElse(() => some(0))) ➔ some(1)
pipe(none, orElse(() => some(0)))    ➔ some(0)

equals

ts
<A>(a: Maybe<A>, b: Maybe<A>) => boolean

Compares one Maybe to another Maybe. Returns false if maybes or the wrapped values are different.

ts
equals(some(1), some(1)) ➔ true
equals(some(1), some(2)) ➔ false
equals(some(1), none)    ➔ false
equals(none, none)       ➔ true

tryCatch

ts
<A>(f: Lazy<A>) => Maybe<A>

Returns a Maybe from a function that might throw.

ts
const unsafeDiv = (top: number, bottom: number) => {
  if (bottom === 0) throw new Error('unsafe division')

  return top / bottom
}

const div = (top: number, bottom: number) => tryCatch(() => unsafeDiv(top, bottom), () => 0)

div(2, 1) ➔ some(2)
div(2, 0) ➔ none

empty

ts
() => None

Returns None.

ts
empty() ➔ none

fromPredicate

ts
<A>(predicate: Predicate<A>): <B extends A>(b: B) => Maybe<B>
<A>(predicate: Predicate<A>): (a: A) => Maybe<A>

Returns Some or None based on the given predicate.

ts
pipe(1, fromPredicate((n: number) => n > 0)) ➔ some(1)
pipe(0, fromPredicate((n: number) => n > 0)) ➔ none

toEither

ts
<E>(f: Lazy<E>) => <A>(ma: Maybe<A>) => Either<E, A>

Returns a Right from a Some or a Left with a default left value if Maybe is None.

ts
pipe(some(1), toEither(() => 0)) ➔ right(1)
pipe(none, toEither(() => 0))    ➔ left(0)

toNullable

ts
<A>(ma: Maybe<A>) => A | null

Extracts the value out of Maybe if it exists, otherwise returns null.

ts
pipe(some(1), toNullable) ➔ 1
pipe(none, toNullable)    ➔ null

toUndefined

ts
<A>(ma: Maybe<A>) => A | undefined

Extracts the value out of Maybe if it exists, otherwise returns undefined.

ts
pipe(some(1), toUndefined) ➔ 1
pipe(none, toUndefined)    ➔ undefined

Released under the MIT License.