Option
A library with a small set of functions that should give you the ability to write a program without undefined
or null
, which makes your program easier to reason about and safer.
Installation
This package can be used with both Node and Deno.
Node
npm i @wentools/option
Deno
From a dependency file
// Preferably in deps.ts
export {
some,
none,
} from 'https://gitlab.com/wentools/option/-/raw/v0.8.6/src/mod.ts'
Consume directly
import {
some,
none,
} from 'https://gitlab.com/wentools/option/-/raw/v0.8.6/src/mod.ts'
Basic usage
The functions some
and none
creates the Option
. If it was the some
function that created the Option
it will hold a value. If it was the none
function it will not hold a value.
Using the methods on the Option
you can safely apply transformations on the value, or resolve the value in a safe way.
import { some, none } from '@wentools/option'
const name1 = {
first: 'John',
middle: some('William'),
last: 'Doe',
}
const name2 = {
first: 'John',
middle: none(),
last: 'Doe',
}
console.log(
`Middle name of ${name1.first} is ${name1.middle
.map((n) => n.toUpperCase())
.unwrapOr('nothing')}`
)
// Middle name of John is WILLIAM
console.log(
`Middle name of ${name2.first} is ${name2.middle
.map((n) => n.toUpperCase())
.unwrapOr('nothing')}`
)
// Middle name of John is nothing
import { assumeOption } from '@wentools/option'
const unsafeFunction = (): string | undefined => {
/* implementation left out for brevity */
}
assumeOption(unsafeFunction()).match({
some: (x) => console.log(x),
none: () => console.log('No data'),
})
Option
Functions for creating some
some(DataType): Option<DataType>
Use this function to create an Option
that holds a value.
If using TypeScript it will try to infer the type. You can also provide the type if you want to be explicit.
const fruit = some('Apple')
fruit.unwrapOr('Banana')
// returns 'Apple'
// Explicit type
const fruit = some<string>('Apple')
fruit.unwrapOr('Banana')
// returns 'Apple'
none
none(): Option<DataType>
Use this function to create an Option
that holds no value.
If using TypeScript it will try to infer the type.
If it can't infer the type it is encouraged to provide the type.
const fruit = none()
fruit.unwrapOr('Banana')
// returns 'Banana'
// Explicit type
const fruit = none<string>()
fruit.unwrapOr('Banana')
// returns 'Banana'
assumeOption
(DataType | undefined | null): Option<DataType>
Use this function to create an Option
that might hold a value.
A good use case is if you're using a library where you have no control but want to use Option
to safely consume it's data.
const fruits = ['Apple']
const fruit = assumeOption(fruits[0])
fruit.unwrapOr('Banana')
// returns 'Apple'
const fruits = ['Apple']
const fruit = assumeOption(fruits[99])
fruit.unwrapOr('Banana')
// returns 'Banana'
Utility functions
transposeOptionToPromise
transposeOptionToPromise(Option<Promise<DataType>>): Promise<Option<DataType>>
Transposes an Option
holding a Promise
to a Promise
holding and Option
const fruit = some(await 'Apple')
await fruit.transposeOptionToPromise().unwrap()
// returns 'Apple'
Option methods
unwrap
unwrap(): DataType
Returns value if Option
is some
. Will throw if Option
is none
.
const fruit = some('Apple')
fruit.unwrap()
// returns 'Apple'
const fruit = none()
fruit.unwrap()
// Will throw error.
// It not recommended to use `unwrap`
// unless you know it's a 'some'.
unwrapOr
unwrapOr(DataType): DataType
Returns value of Option
if it is some
. If Option
is none
it will return the value of the or
parameter.
const fruit = some('Apple')
fruit.unwrapOr('Banana')
// returns 'Apple'
const fruit = none()
fruit.unwrap('Banana')
// returns 'Banana'
unwrapOrElse
unwrapOrElse(() => DataType): DataType
Returns value of Option
if it is some
. If Option
is none
it will run the orElse
function.
const fruit = some('Apple')
fruit.unwrapOrElse((x) => x.toUpperCase())
// returns 'Apple'
const fruit = none()
fruit.unwrapOrElse((x) => x.toUpperCase())
// returns 'BANANA'
match
match({ some(DataType): MatchExpressionType, none(): MatchExpressionType }): MatchExpressionType
const fruit = some('Apple')
fruit.match({
some: (x) => x,
none: () => 'Banana',
})
// returns 'Apple'
const fruit = none()
fruit.match({
some: (x) => x,
none: () => 'Banana',
})
// returns 'Banana'
isSome
isSome(): Boolean
Returns true
if the Option
is some
.
const fruit = some('Apple')
fruit.isSome()
// returns `true`
const fruit = none()
fruit.isSome()
// returns `false`
isNone
isNone(): Boolean
Returns true
if the Option
is none
.
const fruit = some('Apple')
fruit.isNone()
// returns `false`
const fruit = none()
fruit.isNone()
// returns `true`
map
map((DataType) => FnReturnType): Option<FnReturnType>
Run a function that replaces the value of some
. Will do nothing on none
.
const fruit = some('Apple')
fruit.map((x) => x.toUpperCase()).unwrapOr('No fruit :(')
// returns 'APPLE'
const fruit = none()
fruit.map((x) => x.toUpperCase()).unwrapOr('No fruit :(')
// returns 'No fruit :('
mapOr
mapOr((DataType) => FnReturnType, FnReturnType): FnReturnType
Run a function that replaces the value of some
. Will replace none
with some
holding or
.
const fruit = some('Apple')
fruit.mapOr((x) => x.toUpperCase(), 'No fruit :(')
// returns 'APPLE'
const fruit = none()
fruit.mapOr((x) => x.toUpperCase(), 'No fruit :(')
// returns 'No fruit :('
mapOrElse
mapOrElse((DataType) => FnReturnType, () => FnReturnType): FnReturnType
Run a function that replaces the value of some
. Will replace none
with some
holding return value of orElse
function.
const fruit = some('Apple')
fruit.mapOr(
(x) => x.toUpperCase(),
() => 'No fruit'
)
// returns 'APPLE'
const fruit = none()
fruit.mapOr(
(x) => x.toUpperCase(),
() => 'No fruit'
)
// returns 'No fruit'
filter
filter((DataType) => Boolean): Option<DataType>
Returns none
if Option
is none
. Will return some
with value if predicate
returns true
, else it will return none
.
const fruit = some('Apple')
fruit.filter((x) => x === 'Apple').unwrapOr('No fruit')
// returns 'Apple'
fruit.filter((x) => x === 'Banana').unwrapOr('No fruit')
// returns 'No fruit'
const fruit = none()
fruit.filter((x) => x === 'Apple').unwrapOr('No fruit')
// returns 'No fruit'
zip
zip(Option<SecondDataType>): Option<[DataType, SecondDataType]>
Returns a new Option
with the original value and the value of provided option. If either option is none
it will return none
.
const fruit = some('Apple')
fruit.zip(some('Banana')).unwrapOr(['No apple', 'No banana'])
// returns ['Apple', 'Banana']
const fruit = none()
fruit.zip(some('Banana')).unwrapOr(['No apple', 'No banana'])
// returns ['No apple', 'No banana']
and
and(Option<DataType>): Option<DataType>
Returns none if any is none
, else return second option.
const fruit = some('Apple')
fruit.and(some('Banana')).unwrapOr('No fruit')
// returns 'Banana'
const fruit = none()
fruit.and(some('Banana')).unwrapOr('No fruit')
// returns 'No fruit'
andThen
andThen((DataType) => Option<DataType>): Option<DataType>
Returns none if any is none
, else returns result of provided function wrapped in an Option
. Some languages call this function flatMap
.
const fruit = some('Apple')
fruit.andThen((x) => some(x.toUpperCase())).unwrapOr('No fruit')
// returns 'APPLE'
const fruit = none()
fruit.andThen((x) => some(x.toUpperCase())).unwrapOr('No fruit')
// returns 'No fruit'
or
or(Option<DataType>): Option<DataType>
Returns first Option
if it is some
, else provided Option
.
const fruit = some('Apple')
fruit.or(some('Banana')).unwrapOr('No fruit')
// returns 'Apple'
const fruit = none()
fruit.or(some('Banana')).unwrapOr('No fruit')
// returns 'Banana'
const fruit = none()
fruit.or(none()).unwrapOr('No fruit')
// returns 'No fruit'
orElse
orElse(() => Option<DataType>): Option<DataType>
Returns first Option
if it is some
, else returns result of provided function wrapped in an Option
.
const fruit = some('Apple')
fruit.orElse((x) => some(x.toUpperCase())).unwrapOr('No fruit')
// returns 'Apple'
const fruit = none()
fruit.andThen(() => some('Banana')).unwrapOr('No fruit')
// returns 'BANANA'
const fruit = none()
fruit.andThen(() => none()).unwrapOr('No fruit')
// returns 'No fruit'
contains
contains(DataType): boolean
Returns true if the Option
is some
and holds a value equal to the given value.
const fruit = some('Apple')
fruit.contains('Apple')
// returns true
const fruit = none()
fruit.contains('Apple')
// returns false
const fruit = some('Apple')
fruit.contains('Banana')
// returns false