Skip to content

Commit

Permalink
feat: add Maybe.project() (#184)
Browse files Browse the repository at this point in the history
  • Loading branch information
patrickmichalina authored Nov 3, 2022
1 parent 1849e78 commit 9f6409f
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 1 deletion.
5 changes: 5 additions & 0 deletions src/maybe/maybe.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ export interface IMaybe<T> extends IMonad<T> {
*/
flatMapAuto<R>(fn: (v: NonNullable<T>) => R): IMaybe<NonNullable<R>>

/**
* drill into Just values
*/
project<R extends T[keyof T]>(fn: (d: NonNullable<T>) => R): IMaybe<NonNullable<R>>

/**
* Apply a predicate which if met, continues the Maybe chain,
* otherwise return an empty Maybe
Expand Down
48 changes: 47 additions & 1 deletion src/maybe/maybe.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,52 @@ describe('Maybe', () => {

})

describe('chain', () => {
it('should', () => {
interface TestFace { thing: number; name: string }
const obj: TestFace = { thing: 1, name: 'string' }
const chained = maybe(obj)
.project(a => a.name)
.map(a => `${a} hello`)

expect(chained.isSome()).toEqual(true)
expect(chained.valueOrUndefined()).toEqual('string hello')
})

it('should', () => {
const obj = { thing: 1, name: 'string', obj: { initial: 'PJM' } }
const chained = maybe(obj)
.project(a => a.obj)
.project(a => a.initial)
.map(a => `Hello, ${a}`)

expect(chained.isSome()).toEqual(true)
expect(chained.valueOrUndefined()).toEqual('Hello, PJM')
})

it('should', () => {
interface TestFace { thing: number; name: string }
const obj: TestFace = { thing: 1, name: undefined as unknown as string }
const chained = maybe(obj)
.project(a => a.name)
.project(a => a)
.map(a => `${a} hello`)

expect(chained.isNone()).toEqual(true)
expect(chained.valueOrUndefined()).toBeUndefined()
})

it('should', () => {
const obj = undefined as unknown as { name: string }
const chained = maybe(obj)
.project(a => a.name)
.map(a => `${a} hello`)

expect(chained.isNone()).toEqual(true)
expect(chained.valueOrUndefined()).toBeUndefined()
})
})

describe('isSome', () => {
it('false path', () => {
const sut = undefined as boolean | undefined
Expand Down Expand Up @@ -559,7 +605,7 @@ describe('Maybe', () => {
it('should return result object with success', () => {
const hasSome = maybe('hi')
const sut = hasSome.toResult(new Error('oops'))

expect(sut.unwrap()).toEqual('hi')
})

Expand Down
4 changes: 4 additions & 0 deletions src/maybe/maybe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ export class Maybe<T> implements IMaybe<T> {
: new Maybe<NonNullable<R>>(fn(this.value as NonNullable<T>) as NonNullable<R>)
}

public project<R extends T[keyof T]>(fn: (d: NonNullable<T>) => R): IMaybe<NonNullable<R>> {
return this.flatMapAuto(fn)
}

public filter(fn: (f: NonNullable<T>) => boolean): IMaybe<T> {
return this.isNone()
? new Maybe<T>()
Expand Down

0 comments on commit 9f6409f

Please sign in to comment.