Tifi (abbreviation for There, I fixed it!)
🤓 Tifi is a library for functional programming in TypeScript. It solves a problem of the existence of bothundefined
andnull
. Tifi is inspired by the OCaml/Reason utilities for various data types.
Installation
yarn add @mobily/tifi
or with npm
npm install @mobily/tifi --save
Example
TODO
Example
// TODO
Api Reference
Option
type Option<T> = None | Some<T>
fromNullable
If
value
isnull
orundefined
, returnsNone
, otherwise returns a value wrapped inSome
.
fromNullable<T>(value: T | null | undefined): Option<T>
fromNullable(null) // None
fromNullable('string') // Some('string')
fromFalsy
If
value
is falsy, returnsNone
, otherwise returns the value wrapped inSome
.
fromFalsy<T>(value: T): Option<T>
fromFalsy(null) // None
fromFalsy('') // None
fromFalsy(0) // None
fromFalsy('string') // Some('string')
fromFalsy(1) // Some(1)
fromPredicate
If
predicate
returnsfalse
, returnsNone
, otherwise returns a value wrapped inSome
.
fromPredicate<T>(predicate: (value: T) => boolean, value: T): Option<T>
fromPredicate(str => str.length > 10, 'string') // None
fromPredicate(obj => obj.prop === 'string', { prop: 'string' }) // Some({ props: 'string' })
const takeEvenNumber = fromPredicate<number>(x => x % 2 === 0)
takeEvenNumber(4) // Some(4)
takeEvenNumber(1) // None
isSome
If
option
isSome
, returnstrue
.
isSome<T>(option: Option<T>): boolean
const option = fromNullable('string') // Some('string')
isSome(option) // true
isNone
If
option
isNone
, returnstrue
.
isNone<T>(option: Option<T>): boolean
const option = fromNullable(null) // None
isNone(option) // true
flatMap
If
option
isSome
, returns a result offn
, otherwise returnsNone
. Functionfn
must have a return type ofOption
.
flatMap<T, R>(fn: (value: T) => Option<R>, option: Option<T>): Option<R>
pipe(
fromNullable('string'), // Some('string')
flatMap(_ => Some(1)), // Some(1)
getWithDefault(0), // 1
)
pipe(
fromNullable(null), // None
flatMap(_ => Some(1)), // None
getWithDefault(0), // 0
)
mapNullable
If a result of
fn
isnull
orundefined
returnsNone
.
mapNullable<T, R>(fn: (value: T) => R, option: Option<T>): Option<R>
pipe(
fromNullable(null), // None
mapNullable(_ => 1), // Some(1)
getWithDefault(0), // 1
)
map
If
option
isSome
, returnsSome
, otherwise returnsNone
.
map<T, R>(fn: (value: T) => R, option: Option<T>): Option<R>
pipe(
fromNullable(1), // Some(1)
map(n => n * 3), // Some(3)
getWithDefault(0), // 3
)
pipe(
fromNullable(null), // None
map(_ => 1), // None
getWithDefault(0), // 0
)
mapWithDefault
If
option
isSome
, returns a result offn
, otherwise returnsdefaultValue
wrapped inSome
.
mapWithDefault<T, R>(defaultValue: R, fn: (value: T) => R, option: Option<T>): Option<R>
pipe(
fromNullable(null), // None
mapWithDefault(0, _ => 1), // Some(0)
getExn, // 0
)
const mapWithDefaultZero = mapWithDefault(0)
pipe(
fromNullable(null), // None
mapWithDefaultZero(_ => 1), // Some(0)
getExn, // 0
)
getExn
If
option
isSome
, returnsvalue
wrapped inSome
, otherwise raises an error.
getExn<T>(option: Option<T>): T | never
pipe(
fromNullable('string'), // Some('string')
flatMap(_ => None), // None
getExn, // raises an error
)
getWithDefault
If
option
isSome
, returnsvalue
wrapped inSome
, otherwise returnsdefaultValue
.
getWithDefault<T>(defaultValue: T, option: Option<T>): T
pipe(
fromNullable(null), // None
getWithDefault(1), // 1
)
match
If
option
isSome
, returns a result ofsomeFn
, otherwise returns a result ofnoneFn
.
match<T, R>(someFn: (value: T) => R, noneFn: () => R, option: Option<T>): R
pipe(
fromNullable(2), // Some(2)
match(n => n * 10, () => 0), // 20
)
const multiplyByTenIfSome = match<number, number>(n => n * 2)
pipe(
fromNullable(2), // Some(2)
multiplyByTenIfSome(() => 0), // 20
)
const returnZeroIfNone = <T>(fn: (str: T) => number) =>
match<T, number>(fn, () => 0)
pipe(
fromNullable(null), // None
returnZeroIfNone(n => n * 10), // 0
)
toNullable
If
option
isSome
, returnsvalue
, otherwise returnsnull
.
toNullable<T>(option: Option<T>): T | null
pipe(
fromNullable('string'), // Some('string')
flatMap(_ => None), // None
toNullable, // null
)
toUndefined
If
option
isSome
, returnsvalue
, otherwise returnsundefined
.
toUndefined<T>(option: Option<T>): T | undefined
pipe(
fromNullable('string'), // Some('string')
flatMap(_ => None), // None
toUndefined, // undefined
)
List
head
If
list
is empty or the first value isundefined
ornull
, returnsNone
, otherwise returns the first element wrapped inSome
.
head<T>(list: T[]): Option<T>
pipe(
head([1, 2, 3]), // Some(1)
getWithDefault(0), // 1
)
tail
If
list
is empty, returnsNone
, otherwise returns everything except the first element of the list.
tail<T>(list: T[]): Option<T[]>
pipe(
tail([1, 2, 3]), // Some([2, 3])
flatMap(list => get(2, list)), // None
// or flatMap(get(2)), all functions are curried
getWithDefault(0), // 0
)
get
If
index
is larger than a list length, returnsNone
, otherwise returns the nth element in the list wrapped inSome
.
get<T>(index: number, list: T[]): Option<T>
pipe(
get(1, [1, 2, 3]), // Some(2)
map(value => value * 2), // Some(4)
getExn, // 4
)
const getThirdElement = get(2)
pipe(
getThirdElement([1, 3, 6]), // Some(6)
map(value => value * 2), // Some(12)
getExn, // 12
)
getBy
If no element satisfies
predicate
, returnsNone
, otherwise returns the first value wrapped inSome
that satisfies the predicate function.
getBy<T>(predicate: (value: T, index: number) => boolean, list: T[]): Option<T>
pipe(
getBy(str => str.length === 2, ['a', 'ab', 'bc']), // Some('ab')
map(str => `${str}cde`), // Some('abcde')
getWithDefault('xyz'), // abcde
)
const equalsTwo = getBy(value => value === 2)
pipe(
equalsTwo([0, 2, 4]), // Some(2)
map(n => n * 10), // Some(20)
getWithDefault(0), // 20
)
pipe(
equalsTwo([0, 4, 8]), // None
map(n => n * 10), // None
getWithDefault(0), // 0
)
take
If
list
has fewer thann
elements, returnsNone
, otherwise returns a new array with the firstn
elements fromlist
.
take<T>(n: number, list: T[]): Option<T[]>
pipe(
take(2, [1, 2, 3]), // Some([1, 2])
flatMap(list => getBy(value => value % 2 === 0, list)), // Some(2)
// or flatMap(getBy(value => value % 2 === 0)), all functions are curried
getWithDefault(0), // 2
)
const takeThreeElements = take(3)
pipe(
takeThreeElements([0, 2, 4, 6]), // Some([0, 2, 4])
getWithDefault([]), // [0, 2, 4]
)
pipe(
takeThreeElements([0, 2]), // None
getWithDefault([]), // []
)
drop
If
list
has fewer thann
elements, returnsNone
, otherwise returns a list obtained by dropping the firstn
elements.
drop<T>(n: number, list: T[]): Option<T[]>
pipe(
drop(1, [1, 2, 3]), // Some([2, 3])
flatMap(head), // Some(2)
getWithDefault(0), // 2
)
const dropThreeElements = drop(3)
pipe(
dropThreeElements([]), // None
flatMap(head), // None
getWithDefault(0), // 0
)
pipe(
dropThreeElements([1, 2, 3, 4, 5, 6]), // Some([4, 5, 6])
flatMap(tail), // Some([5, 6])
flatMap(head), // Some(5)
getWithDefault(0), // 5
)
splitAt
If
index
is larger than a list length, returnsNone
, otherwise split a list at positionindex
.
splitAt<T>(index: number, list: T[]): Option<[T[], T[]]>
pipe(
splitAt(2, [1, 2, 3, 4]), // Some([[1, 2], [3, 4]])
flatMap(head), // Some([1, 2])
flatMap(list => getBy(value => value % 2 === 0, list)), // Some(2)
// or flatMap(getBy(value => value % 2 === 0)), all functions are curried
getExn, // 2
)
Result
type Result<A, B> = Ok<A> | Error<B>
fromNullable
If
value
isnull
orundefined
, returns a value wrapped inError
, otherwise returns a value wrapped inOk
.
fromNullable<A, B>(error: B, value: A | null | undefined): Result<A, B>
fromNullable('error', null) // Error('error')
fromNullable('error', 'string') // Ok('string')
const fromNullableWithError = fromNullable('error')
fromNullableWithError(null) // Error('error')
fromNullableWithError('string') // Ok('string')
fromFalsy
If
value
is falsy, returns a value wrapped inError
, otherwise returns a value wrapped inOk
.
fromFalsy<A, B>(error: B, value: A | null | undefined): Result<A, B>
fromFalsy('error', null) // Error('error')
fromFalsy('error', '') // Error('error')
fromFalsy('error', 0) // Error('error')
fromFalsy('error', 'string') // Ok('string')
fromFalsy('error', 1) // Ok(1)
const fromFalsyWithError = fromFalsy('error')
fromFalsyWithError(0) // Error('error')
fromFalsyWithError(1) // Ok(1)
fromPredicate
If
predicate
returnsfalse
, returns a value wrapped inError
, otherwise returns a value wrapped inOk
.
fromPredicate<A, B>(predicate: (value: A) => boolean, error: B, value: A): Result<A, B>
fromPredicate(str => str.length > 10, 'error', 'string') // Error('error')
fromPredicate(obj => obj.prop === 'string', 'error', { prop: 'string' }) // Ok({ props: 'string' })
const takeEvenNumber = fromPredicate<number, string>(
x => x % 2 === 0,
'error',
)
takeEvenNumber(4) // Ok(4)
takeEvenNumber(1) // Error('error')
isOk
If
result
isOk
, returnstrue
.
isOk<A, B>(result: Result<A, B>): boolean
const result = fromNullable('error', 'string') // Ok('string')
isOk(result) // true
isError
If
result
isError
, returnstrue
.
isError<A, B>(result: Result<A, B>): boolean
const result = fromNullable('error', null) // Error('error')
isError(result) // true
flatMap
If
result
isOk
, returns the result offn
, otherwise returnsresult
unchanged. Functionfn
must have a return type ofResult
.
flatMap<A, B, R>(fn: (value: A) => Result<R, B>, result: Result<A, B>): Result<R, B>
pipe(
fromNullable('error', null), // Error('error')
flatMap(_ => Ok(1)), // Error('error')
getWithDefault(0), // 0
)
pipe(
fromNullable('error', 'string'), // Ok('string')
flatMap(_ => Ok(1)), // Ok(1)
getWithDefault(0), // 1
)
map
If
result
isOk
, returns the result offn
, otherwise returnsresult
unchanged. Functionfn
takes a value of the same type asvalue
.
map<A, B, R>(fn: (value: A) => R, result: Result<A, B>): Result<R, B>
pipe(
fromNullable('error', 1), // Ok(1)
map(n => n * 3), // Ok(3)
getWithDefault(0), // 3
)
pipe(
fromNullable('error', null), // Error('error')
map(n => n * 3), // Error('error')
getWithDefault(0), // 0
)
mapWithDefault
If
result
isOk
, returns a result offn
, otherwise returnsdefaultValue
wrapped inOk
.
mapWithDefault<A, B, R>(defaultValue: R, fn: (value: A) => R, result: Result<A, B>): Result<R, B>
pipe(
fromNullable('error', null), // Error('error')
mapWithDefault(0, _ => 1), // Ok(0)
getExn, // 0
)
const fromNullableWithError = fromNullable('error')
const mapWithDefaultZero = mapWithDefault(0)
pipe(
fromNullableWithError(null), // Error('error')
mapWithDefaultZero(_ => 1), // Ok(0)
getExn, // 0
)
pipe(
fromNullableWithError(1), // Ok(1)
mapWithDefaultZero(n => n * 10), // Ok(10)
getExn, // 10
)
getExn
If
result
isOk
, returnsvalue
wrapped inOk
, otherwise raises an error.
getExn<A, B>(option: Result<A, B>): A | never
pipe(
fromNullable('error', null), // Error('error')
getExn, // raises an error
)
getWithDefault
If
result
isOk
, returnsvalue
wrapped inOk
, otherwise returnsdefaultValue
.
getWithDefault<A, B>(defaultValue: A, result: Result<A, B>): A
pipe(
fromNullable('error', null), // Error('error')
getWithDefault(1), // 1
)
match
If
result
isOk
, returns a result ofokFn
, otherwise returns a result oferrorFn
.
match<A, B, R>(okFn: (okValue: A) => R, errorFn: (errorValue: B) => R, result: Result<A, B>): R
pipe(
fromNullable('error', 2), // Ok(2)
match(n => n * 10, () => 0), // 20
)
const fromNullableWithError = fromNullable('error')
const matchWithDefaultOk = match<string, string>(str => `${str}!`)
const matchWithDefaultError = <T>(fn: (str: T) => string) =>
match<T, string, string>(fn, str => `${str} x2`)
pipe(
fromNullableWithError('string'), // Ok('string')
matchWithDefaultError(str => `${str}!`), // string!
)
pipe(
fromNullableWithError(null), // Error('error')
matchWithDefaultError(str => `${str}!`), // error x2
)
Contributors
Marcin Dziewulski |
License
The MIT License.
See LICENSE