Skip to content

Commit 509a102

Browse files
feat: add tap methods to Result (#188)
1 parent efe0852 commit 509a102

File tree

3 files changed

+92
-2
lines changed

3 files changed

+92
-2
lines changed

src/result/result.interface.ts

+15
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,21 @@ export interface IResult<T, E> {
2020
mapFail<M>(fn: (err: E) => M): IResult<T, M>
2121
flatMap<M>(fn: (val: T) => IResult<M, E>): IResult<M, E>
2222

23+
/**
24+
* Execute functions with side-effects.
25+
*/
26+
tap(val: Partial<IResultMatchPattern<T, E, void>>): void
27+
28+
/**
29+
* Execute a function with side-effects when maybe is a Fail.
30+
*/
31+
tapFail(f: (val: E) => void): void
32+
33+
/**
34+
* Execute a function with side-effects when maybe is an Ok.
35+
*/
36+
tapOk(f: (val: T) => void): void
37+
2338
/**
2439
* Convert Ok result into Fail using projected value from Ok
2540
*/

src/result/result.spec.ts

+54
Original file line numberDiff line numberDiff line change
@@ -199,4 +199,58 @@ describe('result', () => {
199199
expect(sut.unwrapFail().message).toEqual('error msg')
200200
})
201201
})
202+
203+
describe('tap', () => {
204+
it('should tap.ok', done => {
205+
const sut = ok(1)
206+
207+
sut.tap({
208+
ok: num => {
209+
expect(num).toEqual(1)
210+
done()
211+
},
212+
fail: done
213+
})
214+
})
215+
216+
it('should tap.ok', done => {
217+
const sut = fail<number, string>('failed')
218+
219+
sut.tap({
220+
fail: str => {
221+
expect(str).toEqual('failed')
222+
done()
223+
},
224+
ok: done
225+
})
226+
})
227+
228+
it('should tapOk', done => {
229+
const sut = ok<number, string>(1)
230+
231+
sut.tapOk(num => {
232+
expect(num).toEqual(1)
233+
done()
234+
})
235+
236+
sut.tapFail(() => {
237+
expect(true).toBeFalsy()
238+
done()
239+
})
240+
})
241+
242+
it('should tapFail', done => {
243+
const sut = fail<number, string>('failed')
244+
245+
sut.tapFail(err => {
246+
expect(err).toEqual('failed')
247+
done()
248+
})
249+
250+
sut.tapOk(() => {
251+
expect(true).toBeFalsy()
252+
done()
253+
})
254+
})
255+
})
202256
})

src/result/result.ts

+23-2
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,10 @@ import { IResultMatchPattern, IResult } from './result.interface'
33

44
export abstract class Result<TOk, TFail> implements IResult<TOk, TFail> {
55
public static ok<TOk, TFail>(value: TOk): IResult<TOk, TFail> {
6-
// eslint-disable-next-line @typescript-eslint/no-use-before-define
76
return new OkResult<TOk, TFail>(value)
87
}
98

109
public static fail<TOk, TFail>(value: TFail): IResult<TOk, TFail> {
11-
// eslint-disable-next-line @typescript-eslint/no-use-before-define
1210
return new FailResult<TOk, TFail>(value)
1311
}
1412

@@ -25,6 +23,9 @@ export abstract class Result<TOk, TFail> implements IResult<TOk, TFail> {
2523
abstract flatMap<M>(fn: (val: TOk) => IResult<M, TFail>): IResult<M, TFail>
2624
abstract toFailWhenOk(fn: (val: TOk) => TFail): IResult<TOk, TFail>
2725
abstract toFailWhenOkFrom(val: TFail): IResult<TOk, TFail>
26+
abstract tap(val: IResultMatchPattern<TOk, TFail, void>): void
27+
abstract tapOk(f: (val: TOk) => void): void
28+
abstract tapFail(f: (val: TFail) => void): void
2829
}
2930

3031
export class OkResult<TOk, TFail> extends Result<TOk, TFail> {
@@ -83,6 +84,16 @@ export class OkResult<TOk, TFail> extends Result<TOk, TFail> {
8384
toFailWhenOkFrom(val: TFail): IResult<TOk, TFail> {
8485
return Result.fail(val)
8586
}
87+
88+
tap(val: Partial<IResultMatchPattern<TOk, TFail, void>>): void {
89+
typeof val.ok === 'function' && val.ok(this.successValue)
90+
}
91+
92+
tapOk(fn: (val: TOk) => void): void {
93+
fn(this.successValue)
94+
}
95+
96+
tapFail(): void { }
8697
}
8798

8899
export class FailResult<TOk, TFail> extends Result<TOk, TFail> implements IResult<TOk, TFail> {
@@ -141,4 +152,14 @@ export class FailResult<TOk, TFail> extends Result<TOk, TFail> implements IResul
141152
toFailWhenOkFrom(val: TFail): IResult<TOk, TFail> {
142153
return Result.fail(val)
143154
}
155+
156+
tap(val: Partial<IResultMatchPattern<TOk, TFail, void>>): void {
157+
typeof val.fail === 'function' && val.fail(this.failureValue)
158+
}
159+
160+
tapOk(): void { }
161+
162+
tapFail(fn: (val: TFail) => void): void {
163+
fn(this.failureValue)
164+
}
144165
}

0 commit comments

Comments
 (0)