Skip to content

Commit 1825383

Browse files
feat: introduce maybe.filter (#39)
1 parent e9b240b commit 1825383

File tree

3 files changed

+48
-3
lines changed

3 files changed

+48
-3
lines changed

src/interfaces/maybe.interface.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,6 @@ export interface IMaybe<T> extends IMonad<T> {
6161

6262
// tslint:disable-next-line:readonly-array
6363
of(x?: T, ...args: any[]): IMaybe<T>
64+
65+
filter(fn: (t: T) => boolean): IMaybe<T>
6466
}

src/monads/maybe.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,16 @@ export function maybe<T>(value?: T): IMaybe<NonNullable<T>> {
55
of: maybe,
66
valueOr: (val: NonNullable<T>) => value === null || value === undefined ? val : value as NonNullable<T>,
77
valueOrCompute: (f: () => NonNullable<T>) => value === null || value === undefined ? f() : value as NonNullable<T>,
8-
tap: (obj: Partial<IMaybePattern<T, void>>) => value === null || value === undefined ? obj.none && obj.none() : obj.some && obj.some(value as NonNullable<T>),
8+
tap: (obj: Partial<IMaybePattern<T, void>>) => value === null || value === undefined ? obj.none && obj.none() : obj.some && obj.some(value as NonNullable<T>),
99
tapNone: (f: () => void) => (value === null || value === undefined) && f(),
1010
tapSome: (f: (val: NonNullable<T>) => void) => value !== null && value !== undefined && f(value as NonNullable<T>),
11-
match: <R>(pattern: IMaybePattern<T, R>) => value === null || value === undefined ? pattern.none() : pattern.some(value as NonNullable<T>),
11+
match: <R>(pattern: IMaybePattern<T, R>) => value === null || value === undefined ? pattern.none() : pattern.some(value as NonNullable<T>),
1212
map: <R>(f: (t: NonNullable<T>) => R) => value === null || value === undefined ? maybe<R>() : maybe<R>(f(value as NonNullable<T>)),
13-
flatMap: <R>(f: (d: NonNullable<T>) => IMaybe<R>) => value === null || value === undefined ? maybe<R>() : f(value as NonNullable<T>)
13+
flatMap: <R>(f: (d: NonNullable<T>) => IMaybe<R>) => value === null || value === undefined ? maybe<R>() : f(value as NonNullable<T>),
14+
filter: (fn: (d: NonNullable<T>) => boolean) => value === null || value === undefined
15+
? maybe()
16+
: fn(value as NonNullable<T>)
17+
? maybe(value as NonNullable<T>)
18+
: maybe()
1419
}
1520
}

test/monads/maybe.spec.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,5 +290,43 @@ describe('Maybe', () => {
290290
maybe(sut).tapSome(() => expect(1).toEqual(1))
291291
})
292292
})
293+
294+
describe('when filtering', () => {
295+
it('pass value through if predicate is resolves true', () => {
296+
const thing: { readonly isGreen: boolean } | undefined = { isGreen: true }
297+
298+
expect.assertions(1)
299+
maybe(thing)
300+
.filter(a => a.isGreen === true)
301+
.tap({
302+
some: _thing => expect(_thing).toEqual(thing),
303+
none: () => expect(1).toEqual(1)
304+
})
305+
})
306+
307+
it('should not pass value through if predicate is resolves false', () => {
308+
const thing: { readonly isGreen: boolean } | undefined = { isGreen: false }
309+
310+
expect.assertions(1)
311+
maybe(thing)
312+
.filter(a => a.isGreen === true)
313+
.tap({
314+
some: _thing => expect(true).toBe(false),
315+
none: () => expect(1).toEqual(1)
316+
})
317+
})
318+
319+
it('should handle undefineds correctly', () => {
320+
const thing = undefined as { readonly isGreen: boolean } | undefined
321+
322+
expect.assertions(1)
323+
maybe(thing)
324+
.filter(a => a.isGreen === true)
325+
.tap({
326+
some: _thing => expect(true).toBe(false),
327+
none: () => expect(1).toEqual(1)
328+
})
329+
})
330+
})
293331
})
294332

0 commit comments

Comments
 (0)