UNPKG

ts-results-es

Version:

A TypeScript implementation of Rust's Result and Option objects.

294 lines (247 loc) 9.76 kB
import { Err, Ok, Result } from '../src/index.js'; import { Observable, of } from 'rxjs'; import { elseMap, elseMapTo, filterResultErr, filterResultOk, resultMap, resultMapErr, resultMapErrTo, resultMapTo, resultMergeMap, resultSwitchMap, tapResultErr, tapResultOk, } from '../src/rxjs-operators/index.js'; import { eq } from './util.js'; const goodVal: Observable<Result<string, number>> = of(Ok('good')); const badVal: Observable<Result<string, number>> = of(Err(0)); test('resultMap', () => { const goodValMapped = goodVal.pipe( resultMap((msg) => { eq<typeof msg, string>(true); return !!msg; }), ); eq<typeof goodValMapped, Observable<Result<boolean, number>>>(true); expect(goodValMapped).toMatchObsResult(Ok(true)); const badValMapped = badVal.pipe( resultMap((msg) => { eq<typeof msg, string>(true); return !!msg; }), ); eq<typeof badValMapped, Observable<Result<boolean, number>>>(true); expect(badValMapped).toMatchObsResult(Err(0)); }); test('resultMapErr', () => { const goodValMappedErr = goodVal.pipe( resultMapErr((num) => { eq<typeof num, number>(true); return new Date(num); }), ); eq<typeof goodValMappedErr, Observable<Result<string, Date>>>(true); expect(goodValMappedErr).toMatchObsResult(Ok('good')); const badValMappedErr = badVal.pipe( resultMapErr((num) => { eq<typeof num, number>(true); return new Date(num); }), ); eq<typeof badValMappedErr, Observable<Result<string, Date>>>(true); expect(badValMappedErr).toMatchObsResult(Err(new Date(0))); }); test('resultMapTo', () => { const goodValMappedTo = goodVal.pipe(resultMapTo(500)); eq<typeof goodValMappedTo, Observable<Result<number, number>>>(true); expect(goodValMappedTo).toMatchObsResult(Ok(500)); const badValMappedTo = badVal.pipe(resultMapTo(500)); eq<typeof badValMappedTo, Observable<Result<number, number>>>(true); expect(badValMappedTo).toMatchObsResult(Err(0)); }); test('resultMapErrTo', () => { const goodValMappedErrTo = goodVal.pipe(resultMapErrTo('err')); eq<typeof goodValMappedErrTo, Observable<Result<string, string>>>(true); expect(goodValMappedErrTo).toMatchObsResult(Ok('good')); const badValMappedErrTo = badVal.pipe(resultMapErrTo('err')); eq<typeof badValMappedErrTo, Observable<Result<string, string>>>(true); expect(badValMappedErrTo).toMatchObsResult(Err('err')); }); test('elseMap', () => { const goodValElseMapped = goodVal.pipe( elseMap((num) => { eq<typeof num, number>(true); return new Date(num); }), ); eq<typeof goodValElseMapped, Observable<string | Date>>(true); expect(goodValElseMapped).toMatchObs('good'); const badValElseMapped = badVal.pipe( elseMap((num) => { eq<typeof num, number>(true); return new Date(num); }), ); eq<typeof badValElseMapped, Observable<string | Date>>(true); expect(badValElseMapped).toMatchObs(new Date(0)); }); test('elseMapTo', () => { const goodValElseMapped = goodVal.pipe(elseMapTo(new Date(100))); eq<typeof goodValElseMapped, Observable<string | Date>>(true); expect(goodValElseMapped).toMatchObs('good'); const badValElseMapped = badVal.pipe(elseMapTo(new Date(100))); eq<typeof badValElseMapped, Observable<string | Date>>(true); expect(badValElseMapped).toMatchObs(new Date(100)); }); test('switchMap', async () => { const goodValSwitchMappedToResult = goodVal.pipe( resultSwitchMap((a) => { eq<typeof a, string>(true); return of(Ok(new Date(3)) as Result<Date, string>); }), ); eq<typeof goodValSwitchMappedToResult, Observable<Result<Date, number | string>>>(true); expect(goodValSwitchMappedToResult).toMatchObsResult(Ok(new Date(3))); const goodValSwitchMappedToBadResult = goodVal.pipe( resultSwitchMap((a) => { eq<typeof a, string>(true); return of(Err(new Date(3)) as Result<number, Date>); }), ); eq<typeof goodValSwitchMappedToBadResult, Observable<Result<number, Date | number>>>(true); expect(goodValSwitchMappedToBadResult).toMatchObsResult(Err(new Date(3))); const badValSwitchMappedToResult = badVal.pipe( resultSwitchMap((a) => { eq<typeof a, string>(true); return of(Ok(new Date(3)) as Result<Date, string>); }), ); eq<typeof badValSwitchMappedToResult, Observable<Result<Date, number | string>>>(true); expect(badValSwitchMappedToResult).toMatchObsResult(Err(0)); const goodValSwitchMappedToNonResult = goodVal.pipe( resultSwitchMap((a) => { eq<typeof a, string>(true); return of(new Date(3)); }), ); eq<typeof goodValSwitchMappedToNonResult, Observable<Result<Date, number>>>(true); expect(goodValSwitchMappedToNonResult).toMatchObsResult(Ok(new Date(3))); const badValSwitchMappedToNonResult = badVal.pipe( resultSwitchMap((a) => { eq<typeof a, string>(true); return of(new Date(3)); }), ); eq<typeof badValSwitchMappedToNonResult, Observable<Result<Date, number>>>(true); expect(badValSwitchMappedToNonResult).toMatchObsResult(Err(0)); }); test('switchMap', async () => { const goodValMergeMappedToResult = goodVal.pipe( resultMergeMap((a) => { eq<typeof a, string>(true); return of(Ok(new Date(3)) as Result<Date, string>); }), ); eq<typeof goodValMergeMappedToResult, Observable<Result<Date, number | string>>>(true); expect(goodValMergeMappedToResult).toMatchObsResult(Ok(new Date(3))); const goodValMergeMappedToBadResult = goodVal.pipe( resultMergeMap((a) => { eq<typeof a, string>(true); return of(Err(new Date(3)) as Result<number, Date>); }), ); eq<typeof goodValMergeMappedToBadResult, Observable<Result<number, Date | number>>>(true); expect(goodValMergeMappedToBadResult).toMatchObsResult(Err(new Date(3))); const badValMergeMappedToResult = badVal.pipe( resultMergeMap((a) => { eq<typeof a, string>(true); return of(Ok(new Date(3)) as Result<Date, string>); }), ); eq<typeof badValMergeMappedToResult, Observable<Result<Date, number | string>>>(true); expect(badValMergeMappedToResult).toMatchObsResult(Err(0)); const goodValMergeMappedToNonResult = goodVal.pipe( resultMergeMap((a) => { eq<typeof a, string>(true); return of(new Date(3)); }), ); eq<typeof goodValMergeMappedToNonResult, Observable<Result<Date, number>>>(true); expect(goodValMergeMappedToNonResult).toMatchObsResult(Ok(new Date(3))); const badValMergeMappedToNonResult = badVal.pipe( resultMergeMap((a) => { eq<typeof a, string>(true); return of(new Date(3)); }), ); eq<typeof badValMergeMappedToNonResult, Observable<Result<Date, number>>>(true); expect(badValMergeMappedToNonResult).toMatchObsResult(Err(0)); }); test('filterResultOk', () => { const filteredGoodVal = goodVal.pipe(filterResultOk()); eq<typeof filteredGoodVal, Observable<string>>(true); expect(filteredGoodVal).toMatchObs('good'); let hitBadVal = false; const filteredBadVal = badVal.pipe(filterResultOk()); eq<typeof filteredBadVal, Observable<string>>(true); filteredBadVal.subscribe(() => (hitBadVal = false)); expect(hitBadVal).toEqual(false); }); test('filterResultErr', () => { let hitGoodVal = false; const filteredGoodVal = goodVal.pipe(filterResultErr()); eq<typeof filteredGoodVal, Observable<number>>(true); filteredGoodVal.subscribe(() => (hitGoodVal = false)); expect(hitGoodVal).toEqual(false); const filteredBadVal = badVal.pipe(filterResultErr()); eq<typeof filteredBadVal, Observable<number>>(true); expect(filteredBadVal).toMatchObs(0); }); test('tapResultOk', () => { let hitGoodVal = false; const tappedGoodVal = goodVal.pipe( tapResultOk((val) => { eq<typeof val, string>(true); expect(val).toEqual('good'); hitGoodVal = true; }), ); eq<typeof tappedGoodVal, Observable<Result<string, number>>>(true); expect(tappedGoodVal).toMatchObsResult(Ok('good')); expect(hitGoodVal).toEqual(true); let hitBadVal = false; const tappedBadVal = badVal.pipe( tapResultOk((val) => { eq<typeof val, string>(true); hitBadVal = true; }), ); eq<typeof tappedBadVal, Observable<Result<string, number>>>(true); expect(tappedBadVal).toMatchObsResult(Err(0)); expect(hitBadVal).toEqual(false); }); test('tapResultErr', () => { let hitGoodVal = false; const tappedGoodVal = goodVal.pipe( tapResultErr((val) => { eq<typeof val, number>(true); hitGoodVal = true; }), ); eq<typeof tappedGoodVal, Observable<Result<string, number>>>(true); expect(tappedGoodVal).toMatchObsResult(Ok('good')); expect(hitGoodVal).toEqual(false); let hitBadVal = false; const tappedBadVal = badVal.pipe( tapResultErr((val) => { eq<typeof val, number>(true); expect(val).toEqual(0); hitBadVal = true; }), ); eq<typeof tappedBadVal, Observable<Result<string, number>>>(true); expect(tappedBadVal).toMatchObsResult(Err(0)); expect(hitBadVal).toEqual(true); });