Skip to content

Commit c695fcd

Browse files
feat: add catchResult<TValue, TError>() (#192)
1 parent ecf09b8 commit c695fcd

File tree

3 files changed

+70
-0
lines changed

3 files changed

+70
-0
lines changed

src/result/public_api.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ export * from './result'
22
export * from './result.factory'
33
export * from './result.interface'
44
export * from './transformers/result-to-promise'
5+
export * from './transformers/try-catch-to-result'
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { catchResult } from './try-catch-to-result'
2+
3+
describe(catchResult.name, () => {
4+
it('should try', done => {
5+
function someThrowable(): string {
6+
return 'I worked!'
7+
}
8+
9+
const sut = catchResult(someThrowable)
10+
11+
expect(sut.isOk()).toEqual(true)
12+
expect(sut.unwrap()).toEqual('I worked!')
13+
14+
done()
15+
})
16+
17+
it('should catch', done => {
18+
function someThrowable(): string {
19+
throw new Error('I failed!')
20+
}
21+
22+
const sut = catchResult(someThrowable)
23+
24+
expect(sut.isFail()).toEqual(true)
25+
26+
done()
27+
})
28+
29+
it('should catch with error mapping function', done => {
30+
function someThrowable(): string {
31+
throw new Error('I failed!')
32+
}
33+
34+
class CustomError extends Error {
35+
static fromUnknown(err: unknown): CustomError {
36+
if (err instanceof Error) {
37+
return new CustomError(err.message)
38+
}
39+
return new CustomError('new error')
40+
}
41+
constructor(message?: string) {
42+
super(message)
43+
}
44+
}
45+
46+
const sut = catchResult(someThrowable, CustomError.fromUnknown)
47+
48+
expect(sut.isFail()).toEqual(true)
49+
expect(sut.unwrapFail().message).toEqual('I failed!')
50+
51+
done()
52+
})
53+
})
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { fail, ok } from '../result.factory'
2+
import { IResult } from '../result.interface'
3+
4+
/**
5+
* Ingest a try-catch throwable function so that it doesn't halt the program but instead
6+
* returns an IResult
7+
* @param fn a throwable function
8+
* @returns an IResult object which wraps the execution as either fail or success
9+
*/
10+
export function catchResult<TValue, TError>(fn: () => TValue, errFn?: (err: unknown) => TError): IResult<TValue, TError> {
11+
try {
12+
return ok<TValue, TError>(fn())
13+
} catch(err) {
14+
return fail<TValue, TError>(errFn ? errFn(err) : err as TError)
15+
}
16+
}

0 commit comments

Comments
 (0)