Gathering detailed insights and metrics for @utx/result
Gathering detailed insights and metrics for @utx/result
A typescript implementation of Rust's Result and Option objects.
npm install @utx/result
Typescript
Module System
Node Version
NPM Version
TypeScript (94.77%)
JavaScript (5.23%)
Total Downloads
559
Last Day
1
Last Week
4
Last Month
9
Last Year
253
1 Stars
75 Commits
2 Branches
1 Contributors
Latest Version
3.4.0
Package Id
@utx/result@3.4.0
Unpacked Size
72.46 kB
Size
11.70 kB
File Count
23
NPM Version
8.1.0
Node Version
18.12.1
Cumulative downloads
Total Downloads
Last day
0%
1
Compared to previous day
Last week
300%
4
Compared to previous week
Last month
125%
9
Compared to previous month
Last year
64.3%
253
Compared to previous year
Forked from @vultix's work
A typescript implementation of Rust's Result and Option objects.
Brings compile-time error checking and optional values to typescript.
NPM
1npm install @utx/results
Yarn
1yarn add @utx/results
Convert this:
1import { existsSync, readFileSync } from 'fs'; 2 3function readFile(path: string): string { 4 if (existsSync(path)) { 5 return readFileSync(path); 6 } else { 7 // Callers of readFile have no way of knowing the function can fail 8 throw new Error('invalid path'); 9 } 10} 11 12// This line may fail unexpectedly without warnings from typescript 13const text = readFile('test.txt');
To this:
1import { existsSync, readFileSync } from 'fs'; 2import { Ok, Err, Result } from '@utx/result'; 3 4function readFile(path: string): Result<string, 'invalid path'> { 5 if (existsSync(path)) { 6 return new Ok(readFileSync(path)); // new is optional here 7 } else { 8 return new Err('invalid path'); // new is optional here 9 } 10} 11 12// Typescript now forces you to check whether you have a valid result at compile time. 13const result = readFile('test.txt'); 14if (result.ok) { 15 // text contains the file's content 16 const text = result.val; 17} else { 18 // err equals 'invalid path' 19 const err = result.val; 20}
Convert this:
1declare function getLoggedInUsername(): string | undefined; 2 3declare function getImageURLForUsername(username: string): string | undefined; 4 5function getLoggedInImageURL(): string | undefined { 6 const username = getLoggedInUsername(); 7 if (!username) { 8 return undefined; 9 } 10 11 return getImageURLForUsername(username); 12} 13 14const stringUrl = getLoggedInImageURL(); 15const optionalUrl = stringUrl ? new URL(stringUrl) : undefined; 16console.log(optionalUrl);
To this:
1import { Option, Some, None } from '@utx/result'; 2 3declare function getLoggedInUsername(): Option<string>; 4 5declare function getImageForUsername(username: string): Option<string>; 6 7function getLoggedInImage(): Option<string> { 8 return getLoggedInUsername().andThen(getImageForUsername); 9} 10 11const optionalUrl = getLoggedInImage().map((url) => new URL(stringUrl)); 12console.log(optionalUrl); // Some(URL('...')) 13 14// To extract the value, do this: 15if (optionalUrl.some) { 16 const url: URL = optionalUrl.val; 17}
1import { Result, Err, Ok } from '@utx/result';
1let okResult: Result<number, Error> = Ok(10); 2let errorResult: Result<number, Error> = Err(new Error('bad number!'));
Note: Typescript currently has a bug, making this type narrowing only work when strictNullChecks
is turned on.
1let result: Result<number, Error> = Ok(1); 2if (result.ok) { 3 // Typescript knows that result.val is a number because result.ok was true 4 let number = result.val + 1; 5} else { 6 // Typescript knows that result.val is an `Error` because result.ok was false 7 console.error(result.val.message); 8} 9 10if (result.err) { 11 // Typescript knows that result.val is an `Error` because result.err was true 12 console.error(result.val.message); 13} else { 14 // Typescript knows that result.val is a number because result.err was false 15 let number = result.val + 1; 16}
A stack trace is generated when an Err
is created.
1let error = Err('Uh Oh'); 2let stack = error.stack;
1let goodResult = new Ok(1); 2let badResult = new Err(new Error('something went wrong')); 3 4goodResult.unwrap(); // 1 5badResult.unwrap(); // throws Error("something went wrong")
1let goodResult = Ok(1); 2let badResult = Err(new Error('something went wrong')); 3 4goodResult.expect('goodResult should be a number'); // 1 5badResult.expect('badResult should be a number'); // throws Error("badResult should be a number - Error: something went wrong")
1let goodResult = Ok(1); 2let badResult = Err(new Error('something went wrong')); 3 4goodResult.map((num) => num + 1).unwrap(); // 2 5badResult.map((num) => num + 1).unwrap(); // throws Error("something went wrong") 6 7goodResult 8 .map((num) => num + 1) 9 .mapErr((err) => new Error('mapped')) 10 .unwrap(); // 2 11badResult 12 .map((num) => num + 1) 13 .mapErr((err) => new Error('mapped')) 14 .unwrap(); // throws Error("mapped")
Deprecated in favor of unwrapOr
1let goodResult = Ok(1); 2let badResult = Err(new Error('something went wrong')); 3 4goodResult.unwrapOr(5); // 1 5badResult.unwrapOr(5); // 5
1function checkIsValid(isValid: boolean): Result<void, Error> { 2 if (isValid) { 3 return Ok.EMPTY; 4 } else { 5 return new Err(new Error('Not valid')); 6 } 7}
results
has two helper functions for operating over n Result
objects.
Either returns all of the Ok
values, or the first Err
value
1let pizzaResult: Result<Pizza, GetPizzaError> = getPizzaSomehow(); 2let toppingsResult: Result<Toppings, GetToppingsError> = getToppingsSomehow(); 3 4let result = Result.all(pizzaResult, toppingsResult); // Result<[Pizza, Toppings], GetPizzaError | GetToppingsError> 5 6let [pizza, toppings] = result.unwrap(); // pizza is a Pizza, toppings is a Toppings. Could throw GetPizzaError or GetToppingsError.
Either returns the first Ok
value, or all Err
values
1let url1: Result<string, Error1> = attempt1(); 2let url2: Result<string, Error2> = attempt2(); 3let url3: Result<string, Error3> = attempt3(); 4 5let result = Result.any(url1, url2, url3); // Result<string, Error1 | Error2 | Error3> 6 7let url = result.unwrap(); // At least one attempt gave us a successful url
Allows you to do the same actions as the normal rxjs map operator on a stream of Result objects.
1import { of, Observable } from 'rxjs'; 2import { Ok, Err, Result } from '@utx/result'; 3import { resultMap } from '@utx/result/rxjs-operators'; 4 5const obs$: Observable<Result<number, Error>> = of(Ok(5), Err('uh oh')); 6 7const greaterThanZero = obs$.pipe( 8 resultMap((number) => number > 0), // Doubles the value 9); // Has type Observable<Result<boolean, 'uh oh'>> 10 11greaterThanZero.subscribe((result) => { 12 if (result.ok) { 13 console.log('Was greater than zero: ' + result.val); 14 } else { 15 console.log('Got Error Message: ' + result.val); 16 } 17}); 18 19// Logs the following: 20// Got number: 10 21// Got Error Message: uh oh
1import { resultMapErr } from '@utx/result/rxjs-operators';
Behaves exactly the same as resultMap, but maps the error value.
1import { resultMapTo } from '@utx/result/rxjs-operators';
Behaves the same as resultMap, but takes a value instead of a function.
1import { resultMapErrTo } from '@utx/result/rxjs-operators';
Behaves the same as resultMapErr, but takes a value instead of a function.
Allows you to turn a stream of Result objects into a stream of values, transforming any errors into a value.
Similar to calling the else function, but works on a stream of Result objects.
1import { of, Observable } from 'rxjs'; 2import { Ok, Err, Result } from '@utx/result'; 3import { elseMap } from '@utx/result/rxjs-operators'; 4 5const obs$: Observable<Result<number, Error>> = of(Ok(5), Err(new Error('uh oh'))); 6 7const doubled = obs$.pipe( 8 elseMap((err) => { 9 console.log('Got error: ' + err.message); 10 11 return -1; 12 }), 13); // Has type Observable<number> 14 15doubled.subscribe((number) => { 16 console.log('Got number: ' + number); 17}); 18 19// Logs the following: 20// Got number: 5 21// Got error: uh oh 22// Got number: -1
1import { elseMapTo } from '@utx/result/rxjs-operators';
Behaves the same as elseMap, but takes a value instead of a function.
Allows you to do the same actions as the normal rxjs switchMap and rxjs switchMap operator on a stream of Result objects.
Merging or switching from a stream of Result<T, E>
objects onto a stream of <T2>
objects turns the stream into a
stream of Result<T2, E>
objects.
Merging or switching from a stream of Result<T, E>
objects onto a stream of Result<T2, E2>
objects turn the stream
into a stream of Result<T2, E | T2>
objects.
1import { of, Observable } from 'rxjs'; 2import { Ok, Err, Result } from '@utx/result'; 3import { resultMergeMap } from '@utx/result/rxjs-operators'; 4 5const obs$: Observable<Result<number, Error>> = of(new Ok(5), new Err(new Error('uh oh'))); 6 7const obs2$: Observable<Result<string, CustomError>> = of(new Ok('hi'), new Err(new CustomError('custom error'))); 8 9const test$ = obs$.pipe( 10 resultMergeMap((number) => { 11 console.log('Got number: ' + number); 12 13 return obs2$; 14 }), 15); // Has type Observable<Result<string, CustomError | Error>> 16 17test$.subscribe((result) => { 18 if (result.ok) { 19 console.log('Got string: ' + result.val); 20 } else { 21 console.log('Got error: ' + result.val.message); 22 } 23}); 24 25// Logs the following: 26// Got number: 5 27// Got string: hi 28// Got error: custom error 29// Got error: uh oh
Converts an Observable<Result<T, E>>
to an Observble<T>
by filtering out the Errs and mapping to the Ok values.
1import { of, Observable } from 'rxjs'; 2import { Ok, Err, Result } from '@utx/result'; 3import { filterResultOk } from '@utx/result/rxjs-operators'; 4 5const obs$: Observable<Result<number, Error>> = of(new Ok(5), new Err(new Error('uh oh'))); 6 7const test$ = obs$.pipe(filterResultOk()); // Has type Observable<number> 8 9test$.subscribe((result) => { 10 console.log('Got number: ' + result); 11}); 12 13// Logs the following: 14// Got number: 5
Converts an Observable<Result<T, E>>
to an Observble<T>
by filtering out the Oks and mapping to the error values.
1import { of, Observable } from 'rxjs'; 2import { Ok, Err, Result } from '@utx/result'; 3import { filterResultOk } from '@utx/result/rxjs-operators'; 4 5const obs$: Observable<Result<number, Error>> = of(new Ok(5), new Err(new Error('uh oh'))); 6 7const test$ = obs$.pipe(filterResultOk()); // Has type Observable<number> 8 9test$.subscribe((result) => { 10 console.log('Got number: ' + result); 11}); 12 13// Logs the following: 14// Got number: 5
No vulnerabilities found.
No security vulnerabilities found.