Option
Option
represents an optional value: every Option
is either Some
, and contains a value, or None
, and it's empty.
It is commonly used to represent the result of a function that may not return a value due to failure or missing data, such as a network request, a file read, or a database query.
Constructor
some
Constructs a Some
Option
, representing an optional value that exists.
import { Option } from 'funkcia';
// ┌─── Option<number>
// â–¼
const option = Option.some(10);
// Output: Some(10)
of
Constructs a Some
Option
, representing an optional value that exists.
import { Option } from 'funkcia';
// ┌─── Option<number>
// â–¼
const option = Option.of(10);
// Output: Some(10)
none
Constructs a None
Option
, representing an optional value that does not exist.
import { Option } from 'funkcia';
function divide(dividend: number, divisor: number): Option<number> {
if (divisor === 0) {
return Option.none();
}
return Option.some(dividend / divisor);
}
fromNullable
Constructs an Option
from a nullable value.
If the value is null
or undefined
, it returns an Option.None
. Otherwise, it returns an Option.Some
containing the value.
import { Option } from 'funkcia';
declare const user: User | null
// ┌─── Option<User>
// â–¼
const option = Option.fromNullable(user);
fromFalsy
Constructs an Option
from a falsy value.
If the value is falsy, it returns an Option.None
. Otherwise, it returns an Option.Some
with the value.
import { Option } from 'funkcia';
function getEnv(variable: string): string {
return process.env[variable] ?? '';
}
// ┌─── Option<string>
// â–¼
const option = Option.fromFalsy(getEnv('BASE_URL'));
try
Constructs an Option
from a function that may throw.
If the function throws or returns null
or undefined
, it returns an Option.None
. Otherwise, it returns an Option.Some
with the value.
import { Option } from 'funkcia';
// ┌─── Option<URL>
// â–¼
const url = Option.try(() => new URL('example.com'));
// Output: None
firstSomeOf
Returns the first Option.Some
value in the iterable. If all values are Option.None
, returns Option.None
.
import { Option } from 'funkcia';
interface ContactInformation {
primary: Option<string>;
secondary: Option<string>;
emergency: Option<string>;
}
declare const contact: ContactInformation;
// ┌─── Option<string>
// â–¼
const option = Option.firstSomeOf([
contact.primary,
contact.secondary,
contact.emergency,
]);
predicate
Returns a function that asserts that a value passes the test implemented by the provided function, creating an Option.Some
narrowing down the value to the provided type predicate if the predicate is fulfilled. If the test fails, returns an Option.None
instead.
import { Option } from 'funkcia';
// ┌─── (shape: Shape) => Option<Circle>
// â–¼
const ensureCircle = Option.predicate(
(shape: Shape): shape is Circle => shape.kind === 'circle',
);
declare const input: Shape;
// ┌─── Option<Circle>
// â–¼
const option = ensureCircle(input);
// ┌─── (value: number) => Option<number>
// â–¼
const ensurePositive = Option.predicate(
(value: number) => value > 0,
);
// ┌─── Option<number>
// â–¼
const option = ensurePositive(input);
fun
This method offers improved type inference for the function's return value and guarantees that the function will always return an Option
.
Declare a function that always returns an Option
.
import { Option } from 'funkcia';
// When defining a normal function allowing typescript to infer
// the return type, sometimes the return type will be
// a union of `Option<T>` and `Option<U>` or `Option<never>`
function hasAcceptedTermsOfService(user: User) {
if (typeof user.termsOfService !== 'boolean')
return Option.none();
return user.termsOfService
? Option.some('ACCEPTED' as const)
: Option.some('DECLINED' as const);
}
// ┌─── Option<'ACCEPTED'> | Option<'DECLINED'> | Option<never>
// â–¼
const option = hasAcceptedTermsOfService(user);
// When using the `fun` method, the return type is always `Option<T | U>`
const improvedHasAcceptedTermsOfService = Option.fun(hasAcceptedTermsOfService);
// ┌─── Option<'ACCEPTED' | 'DECLINED'>
// â–¼
const option = improvedHasAcceptedTermsOfService(user);
enhance
Converts a function that may throw or return a nullable value to an enhanced function that returns an Option
.
import { Option } from 'funkcia';
// ┌─── (text: string, reviver?: Function) => Option<any>
// â–¼
const safeJsonParse = Option.enhance(JSON.parse);
// ┌─── Option<any>
// â–¼
const profile = safeJsonParse('{ "name": "John Doe" }');
// Output: Some({ name: 'John Doe' })
values
Given an array of Option
s, returns an array containing only the values inside Some
.
import { Option } from 'funkcia';
// ┌─── number[]
// â–¼
const output = Option.values([
Option.some(1),
Option.none<number>(),
Option.some(3),
]);
// Output: [1, 3]
is
Asserts that an unknown value is an Option
.
import { Option } from 'funkcia';
declare const maybeAnOptionWithUser: unknown;
if (Option.is(maybeAnOptionWithUser)) {
const user = .filter(isUser);
// â–²
// └─── Option
}
Instance methods
map
Applies a callback function to the value of the Option
when it is Some
, returning a new Option
containing the new value.
import { Option } from 'funkcia';
// ┌─── Option<number>
// â–¼
const option = Option.of(10).map(number => number * 2);
// Output: Some(20)
andThen
Applies a callback function to the value of the Option
when it is Some
, and returns the new value. Similar to chain
(also known as flatMap
), with the difference that the callback must return an Option
, not a raw value.
import { Option } from 'funkcia';
declare function readFile(path: string): Option<string>;
declare function parseJsonFile(contents: string): Option<FileContent>;
// ┌─── Option<FileContent>
// â–¼
const option = readFile('data.json').andThen(parseJsonFile);
filter
Asserts that the Option
value passes the test implemented by the provided function. If the test fails, the value is filtered out of the Option
, returning a None
instead.
import { Option } from 'funkcia';
declare const input: Shape;
// ┌─── Option<Circle>
// â–¼
const circle = Option.of(input).filter(
(shape): shape is Circle => shape.kind === 'circle',
);
// ┌─── Option<User>
// â–¼
const option = Option.of(user).filter((user) => user.age >= 21);
or
Replaces the current Option
with the provided fallback Option
when it is None
.
If the current Option
is Some
, it returns the current Option
.
import { Option } from 'funkcia';
// Output: Some('Paul')
const option = Option.some('Paul')
.or(() => Option.some('John'));
// Output: Some('John')
const greeting = Option.none()
.or(() => Option.some('John'));
zip
Combines two Option
s into a single Option
containing a tuple of their values, if both Option
s are Some
variants, otherwise, returns None
.
import { Option } from 'funkcia';
const first = Option.some('hello');
const second = Option.some('world');
// ┌─── Option<[string, string]>
// â–¼
const strings = first.zip(second);
// Output: Some(['hello', 'world'])
zipWith
Combines two Option
s into a single Option
. The new value is produced by applying the given function to both values, if both Option
s are Some
variants, otherwise, returns None
.
import { Option } from 'funkcia';
const first = Option.some('hello');
const second = Option.some('world');
// ┌─── Option<string>
// â–¼
const greeting = first.zipWith(second, (a, b) => `${a} ${b}`);
// Output: Some('hello world')
match
Compare the Option
against the possible patterns and then execute code based on which pattern matches.
import { Option } from 'funkcia';
declare function readFile(path: string): Option<string>;
declare function parseJsonFile(contents: string): Option<FileContent>;
// ┌─── string
// â–¼
const userGreeting = readFile('data.json')
.andThen(parseJsonFile)
.match({
Some(contents) {
return processFile(contents);
},
None() {
return 'File is invalid JSON';
},
});
unwrap
Throws UnwrapError
if the Option
is None
.
Unwraps the Option
value.
import { Option } from 'funkcia';
// ┌─── User
// â–¼
const user = Option.some(databaseUser).unwrap();
const team = Option.none().unwrap();
// Output: Uncaught exception: 'called "Option.unwrap()" on a "None" value'
unwrapOr
Unwraps the Option
value.
If the Option is None
, returns the result of the provided callback.
import { Option } from 'funkcia';
// ┌─── string
// â–¼
const baseUrl = Option.some(process.env.BASE_URL)
.unwrapOr(() => 'http://localhost:3000');
// Output: 'https://funkcia.lukemorales.io'
const apiKey = Option.none()
.unwrapOr(() => 'sk_test_9FK7CiUnKaU');
// Output: 'sk_test_9FK7CiUnKaU'
unwrapOrNull
Unwraps the value of the Option
if it is a Some
, otherwise returns null
.
import { Option } from 'funkcia';
declare const findUserById: (id: string) => Option<User>;
// ┌─── User | null
// â–¼
const user = findUserById('user_123').unwrapOrNull();
unwrapOrUndefined
Unwraps the value of the Option
if it is a Some
, otherwise returns undefined
.
import { Option } from 'funkcia';
declare const findUserById: (id: string) => Option<User>;
// ┌─── User | undefined
// â–¼
const user = findUserById('user_123').unwrapOrUndefined();
expect
Throws the provided Error if the Option
is None
.
Unwraps the Option
value.
import { Option } from 'funkcia';
declare function findUserById(id: string): Option<User>;
// ┌─── User
// â–¼
const user = findUserById('user_123').expect(
() => new UserNotFound(userId),
);
const anotherUser = findUserById('invalid_id').expect(
() => new UserNotFound('invalid_id'),
);
// Output: Uncaught exception: 'User not found: "user_123"'
contains
Verifies if the Option
contains a value that passes the test implemented by the provided function.
Returns
true
if the predicate is fullfiled by the wrapped value.If the predicate is not fullfiled or if the
Option
isNone
, returnsfalse
.
import { Option } from 'funkcia';
// ┌─── boolean
// â–¼
const isPositive = Option.some(10).contains(num => num > 0);
// Output: true
toResult
Converts an Option
to a Result
.
If Option
is Some
, returns a Result.ok
. If Option
is None
, returns a Result.error
with a NoValueError
or a custom error.
import { Option } from 'funkcia';
declare function findUserById(id: string): Option<User>;
// ┌─── Result<User, NoValueError>
// â–¼
const authorizedUser = findUserById('user_123').toResult();
// ┌─── Result<User, UserNotFound>
// â–¼
const authorizedUser = findUserById('user_123')
.toResult(() => new UserNotFound('user_123'));
toAsyncOption
Converts the Option
to an AsyncOption
.
import { Option } from 'funkcia';
declare function readFile(path: string): Option<string>;
declare function parseJsonFile(contents: string): Option<FileContent>;
// ┌─── AsyncOption<FileContent>
// â–¼
const asyncFile = readFile('data.json')
.andThen(parseJsonFile)
.toAsyncOption();
// Output: Promise<Some(FileContent)>
toAsyncResult
Converts the Option
to an AsyncResult
.
import { Option } from 'funkcia';
declare function readFile(path: string): Option<string>;
declare function parseJsonFile(contents: string): Option<FileContent>;
// ┌─── AsyncResult<FileContent, NoValueError>
// â–¼
const asyncFile = readFile('data.json')
.andThen(parseJsonFile)
.toAsyncResult();
// Output: Promise<Ok(FileContent)>
// ┌─── AsyncResult<FileContent, InvalidFile>
// â–¼
const asyncFile = readFile('data.json')
.andThen(parseJsonFile)
.toAsyncResult(() => new InvalidFile('data.json'));
// Output: Promise<Ok(FileContent)>
toArray
Converts an Option
to an array.
If Option
is Some
, returns an array with the value. If Option
is None
, returns an empty array.
import { Option } from 'funkcia';
// ┌─── number[]
// â–¼
const output = Option.some(10).toArray();
// Output: [10]
tap
Calls the function with the Option
value, then returns the Option
itself.
The return value of the provided function is ignored. This allows "tapping into" a function sequence in a pipe, to perform side effects on intermediate results
import { Option } from 'funkcia';
// ┌─── Option<number>
// â–¼
const option = Option.some(10)
.tap((value) => console.log(value)); // Console output: 10
isSome
Returns true
if the Option
contains a value.
import { Option } from 'funkcia';
declare function findUserById(id: string): Option<User>;
const user = findUserById('user_123');
if (user.isSome()) {
return user.unwrap(); // `unwrap` will not throw
}
isNone
Returns true
if the Option
is empty.
import { Option } from 'funkcia';
declare function findUserByEmail(email: string): Option<User>;
const user = findUserByEmail(data.email);
if (user.isNone()) {
return await createUser(data);
}
return user.unwrap();
equals
Compares the Option
with another Option
and returns true
if they are equal.
import { Option } from 'funkcia';
const option = Option.of(10).equals(Option.some(10));
// Output: true
Last updated
Was this helpful?