Skip to content

Commit 8fcba51

Browse files
feat(maybe): introduce valueOrUndefined function (#41)
1 parent 26519dd commit 8fcba51

File tree

3 files changed

+38
-8
lines changed

3 files changed

+38
-8
lines changed

src/interfaces/maybe.interface.ts

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,20 @@ export interface IMaybePattern<TIn, TOut> {
1919
* Abstraction for handling possibility of undefined values
2020
*/
2121
export interface IMaybe<T> extends IMonad<T> {
22+
23+
// tslint:disable-next-line:readonly-array
24+
of(x?: T, ...args: any[]): IMaybe<T>
25+
2226
/**
2327
* Unwrap a Maybe with a default value
2428
*/
2529
valueOr(val: NonNullable<T>): T
2630

31+
/**
32+
* Unwrap a Maybe with its value or return undefined if its empty
33+
*/
34+
valueOrUndefined(): T | undefined
35+
2736
/**
2837
* Unwrap a Maybe with a default computed value
2938
*/
@@ -33,12 +42,12 @@ export interface IMaybe<T> extends IMonad<T> {
3342
* Execute functions with side-effects.
3443
*/
3544
tap(val: Partial<IMaybePattern<T, void>>): void
36-
45+
3746
/**
3847
* Execute a function with side-effects when maybe is a none.
3948
*/
4049
tapNone(f: () => void): void
41-
50+
4251
/**
4352
* Execute a function with side-effects when maybe is a some.
4453
*/
@@ -50,17 +59,18 @@ export interface IMaybe<T> extends IMonad<T> {
5059
match<R>(pattern: IMaybePattern<T, R>): R
5160

5261
/**
53-
* Combine multiple maybe
62+
* Map output of non-empty data to a new value
5463
*/
5564
map<R>(f: (t: T) => R): IMaybe<R>
5665

5766
/**
58-
* Combine multiple maybe
67+
* Combine multiple Maybe
5968
*/
6069
flatMap<R>(f: (t: T) => IMaybe<R>): IMaybe<R>
6170

62-
// tslint:disable-next-line:readonly-array
63-
of(x?: T, ...args: any[]): IMaybe<T>
64-
71+
/**
72+
* Apply a predicate which if met, continues the Maybe chain,
73+
* otherwise return an empty Maybe
74+
*/
6575
filter(fn: (t: T) => boolean): IMaybe<T>
6676
}

src/monads/maybe.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { IMaybe, IMaybePattern } from "../interfaces"
33
const isEmpty = <T>(value: T) => value === null || value === undefined
44
const isNotEmpty = <T>(value: T) => !isEmpty(value)
55
const valueOr = <T>(value?: T) => (val: NonNullable<T>) => isEmpty(value) ? val : value as NonNullable<T>
6+
const valueOrUndefined = <T>(value?: T) => () => isEmpty(value) ? undefined : value as NonNullable<T>
67
const valueOrCompute = <T>(value?: T) => (fn: () => NonNullable<T>) => isEmpty(value) ? fn() : value as NonNullable<T>
78
const tap = <T>(value?: T) => (obj: Partial<IMaybePattern<T, void>>) => isEmpty(value) ? obj.none && obj.none() : obj.some && obj.some(value as NonNullable<T>)
89
const tapNone = <T>(value?: T) => (fn: () => void) => (isEmpty(value)) && fn()
@@ -15,6 +16,7 @@ export const maybe = <T>(value?: T): IMaybe<NonNullable<T>> => {
1516
return {
1617
of: maybe,
1718
valueOr: valueOr(value),
19+
valueOrUndefined: valueOrUndefined(value),
1820
valueOrCompute: valueOrCompute(value),
1921
tap: tap(value),
2022
tapNone: tapNone(value),

test/monads/maybe.spec.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,5 +328,23 @@ describe('Maybe', () => {
328328
})
329329
})
330330
})
331-
})
332331

332+
333+
334+
335+
describe('when returning a value or undefined', () => {
336+
it('should handle "none" case', () => {
337+
const sut = undefined as string | undefined
338+
const maybeAString = maybe(sut).valueOrUndefined()
339+
340+
expect(maybeAString).toBeUndefined()
341+
})
342+
343+
it('should handle "some" case', () => {
344+
const sut = 'actual input' as string | undefined
345+
const maybeAString = maybe(sut).valueOrUndefined()
346+
347+
expect(maybeAString).toEqual('actual input')
348+
})
349+
})
350+
})

0 commit comments

Comments
 (0)