ts-results
Advanced tools
Comparing version 2.0.1 to 3.0.0
148
index.d.ts
@@ -1,42 +0,142 @@ | ||
export declare class Err<E> { | ||
interface BaseResult<T, E> extends Iterable<T extends Iterable<infer U> ? U : never> { | ||
/** `true` when the result is Ok */ readonly ok: boolean; | ||
/** `true` when the result is Err */ readonly err: boolean; | ||
/** | ||
* Returns the contained `Ok` value, if exists. Throws an error if not. | ||
* @param msg the message to throw if no Ok value. | ||
*/ | ||
expect(msg: string): T; | ||
/** | ||
* Returns the contained `Ok` value. | ||
* Because this function may throw, its use is generally discouraged. | ||
* Instead, prefer to handle the `Err` case explicitly. | ||
* | ||
* Throws if the value is an `Err`, with a message provided by the `Err`'s value. | ||
*/ | ||
unwrap(): T; | ||
/** | ||
* Returns the contained `Ok` value or a provided default. | ||
* | ||
* @see unwrapOr | ||
* @deprecated in favor of unwrapOr | ||
*/ | ||
else<T2>(val: T2): T | T2; | ||
/** | ||
* Returns the contained `Ok` value or a provided default. | ||
* | ||
* (This is the `unwrap_or` in rust) | ||
*/ | ||
unwrapOr<T2>(val: T2): T | T2; | ||
/** | ||
* Calls `mapper` if the result is `Ok`, otherwise returns the `Err` value of self. | ||
* This function can be used for control flow based on `Result` values. | ||
*/ | ||
andThen<T2, E2>(mapper: (val: T) => Result<T2, E2>): Result<T2, E | E2>; | ||
/** | ||
* Maps a `Result<T, E>` to `Result<U, E>` by applying a function to a contained `Ok` value, | ||
* leaving an `Err` value untouched. | ||
* | ||
* This function can be used to compose the results of two functions. | ||
*/ | ||
map<U>(mapper: (val: T) => U): Result<U, E>; | ||
/** | ||
* Maps a `Result<T, E>` to `Result<T, F>` by applying a function to a contained `Err` value, | ||
* leaving an `Ok` value untouched. | ||
* | ||
* This function can be used to pass through a successful result while handling an error. | ||
*/ | ||
mapErr<F>(mapper: (val: E) => F): Result<T, F>; | ||
} | ||
export declare function Err<E>(val: E): Err<E>; | ||
/** | ||
* Contains the error value | ||
*/ | ||
export declare class Err<E> implements BaseResult<never, E> { | ||
/** An empty Err */ | ||
static readonly EMPTY: Err<void>; | ||
readonly ok: false; | ||
readonly err: true; | ||
readonly val: E; | ||
static readonly EMPTY: Err<void>; | ||
readonly ok = false; | ||
readonly err = true; | ||
[Symbol.iterator](): Iterator<never, never, any>; | ||
constructor(val: E); | ||
/** | ||
* If the result has a value returns that value. Otherwise returns the passed in value. | ||
* @param val the value to replace the error with | ||
* @deprecated in favor of unwrapOr | ||
* @see unwrapOr | ||
*/ | ||
else<T2>(val: T2): T2; | ||
unwrapOr<T2>(val: T2): T2; | ||
expect(msg: string): never; | ||
unwrap(): never; | ||
map<T2>(mapper: (val: never) => T2): Err<E>; | ||
map<T2>(_mapper: (val: never) => T2): Err<E>; | ||
andThen<T2, E2>(op: (val: never) => Result<T2, E2>): Err<E>; | ||
mapErr<E2>(mapper: (err: E) => E2): Err<E2>; | ||
} | ||
export declare class Ok<T> { | ||
export declare function Ok<T>(val: T): Ok<T>; | ||
/** | ||
* Contains the success value | ||
*/ | ||
export declare class Ok<T> implements BaseResult<T, never> { | ||
static readonly EMPTY: Ok<void>; | ||
readonly ok: true; | ||
readonly err: false; | ||
readonly val: T; | ||
static readonly EMPTY: Ok<void>; | ||
readonly ok = true; | ||
readonly err = false; | ||
/** | ||
* Helper function if you know you have an Ok<T> and T is iterable | ||
*/ | ||
[Symbol.iterator](): Iterator<T extends Iterable<infer U> ? U : never>; | ||
constructor(val: T); | ||
/** | ||
* If the result has a value returns that value. Otherwise returns the passed in value. | ||
* @param val the value to replace the error with | ||
* @see unwrapOr | ||
* @deprecated in favor of unwrapOr | ||
*/ | ||
else<T2>(val: T2): T; | ||
expect(msg: string): T; | ||
else(_val: unknown): T; | ||
unwrapOr(_val: unknown): T; | ||
expect(_msg: string): T; | ||
unwrap(): T; | ||
map<T2>(mapper: (val: T) => T2): Ok<T2>; | ||
mapErr<E2>(mapper: (err: never) => E2): Ok<T>; | ||
andThen<T2, E2>(mapper: (val: T) => Result<T2, E2>): Result<T2, E2>; | ||
mapErr<E2>(_mapper: (err: never) => E2): Ok<T>; | ||
/** | ||
* Returns the contained `Ok` value, but never throws. | ||
* Unlike `unwrap()`, this method doesn't throw and is only callable on an Ok<T> | ||
* | ||
* Therefore, it can be used instead of `unwrap()` as a maintainability safeguard | ||
* that will fail to compile if the error type of the Result is later changed to an error that can actually occur. | ||
* | ||
* (this is the `into_ok()` in rust) | ||
*/ | ||
safeUnwrap(): T; | ||
} | ||
export declare type Result<T, E> = (Ok<T> | Err<E>) & { | ||
map<T2>(mapper: (val: T) => T2): Result<T2, E>; | ||
mapErr<E2>(mapper: (val: E) => E2): Result<T, E2>; | ||
}; | ||
export declare type Result<T, E> = (Ok<T> | Err<E>) & BaseResult<T, E>; | ||
export declare type ResultOkType<T extends Result<any, any>> = T extends Result<infer U, any> ? U : never; | ||
export declare type ResultErrType<T extends Result<any, any>> = T extends Result<any, infer U> ? U : never; | ||
export declare function Results<T1, E1, T2, E2>(result1: Result<T1, E1>, result2: Result<T2, E2>): Result<[T1, T2], E1 | E2>; | ||
export declare function Results<T1, E1, T2, E2, T3, E3>(result1: Result<T1, E1>, result2: Result<T2, E2>, result3: Result<T3, E3>): Result<[T1, T2, T3], E1 | E2 | E3>; | ||
export declare function Results<T1, E1, T2, E2, T3, E3, T4, E4>(result1: Result<T1, E1>, result2: Result<T2, E2>, result3: Result<T3, E3>, result4: Result<T4, E4>): Result<[T1, T2, T3, T4], E1 | E2 | E3 | E4>; | ||
export declare function Results(...results: Result<any, any>[]): Result<any[], any>; | ||
export declare type ResultOkTypes<T extends Result<any, any>[]> = { | ||
[key in keyof T]: T[key] extends Result<infer U, any> ? U : never; | ||
}; | ||
export declare type ResultErrTypes<T extends Result<any, any>[]> = { | ||
[key in keyof T]: T[key] extends Result<any, infer U> ? U : never; | ||
}; | ||
export declare namespace Result { | ||
/** | ||
* Parse a set of `Result`s, returning an array of all `Ok` values. | ||
* Short circuits with the first `Err` found, if any | ||
*/ | ||
function all<T extends Result<any, any>[]>(...results: T): Result<ResultOkTypes<T>, ResultErrTypes<T>[number]>; | ||
/** | ||
* Parse a set of `Result`s, short-circuits when an input value is `Ok`. | ||
* If no `Ok` is found, returns an `Err` containing the collected error values | ||
*/ | ||
function any<T extends Result<any, any>[]>(...results: T): Result<ResultOkTypes<T>[number], ResultErrTypes<T>>; | ||
/** | ||
* Wrap an operation that may throw an Error (`try-catch` style) into checked exception style | ||
* @param op The operation function | ||
*/ | ||
function wrap<T, E = unknown>(op: () => T): Result<T, E>; | ||
/** | ||
* Wrap an async operation that may throw an Error (`try-catch` style) into checked exception style | ||
* @param op The operation function | ||
*/ | ||
function wrapAsync<T, E = unknown>(op: () => Promise<T>): Promise<Result<T, E>>; | ||
} | ||
export {}; | ||
//# sourceMappingURL=index.d.ts.map |
267
index.js
@@ -1,83 +0,216 @@ | ||
export class Err { | ||
constructor(val) { | ||
this.val = val; | ||
this.ok = false; | ||
this.err = true; | ||
(function (factory) { | ||
if (typeof module === "object" && typeof module.exports === "object") { | ||
var v = factory(require, exports); | ||
if (v !== undefined) module.exports = v; | ||
} | ||
else if (typeof define === "function" && define.amd) { | ||
define(["require", "exports"], factory); | ||
} | ||
})(function (require, exports) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Result = exports.Ok = exports.Err = void 0; | ||
/** | ||
* If the result has a value returns that value. Otherwise returns the passed in value. | ||
* @param val the value to replace the error with | ||
* Contains the error value | ||
*/ | ||
else(val) { | ||
return val; | ||
} | ||
expect(msg) { | ||
let value = this.val.toString(); | ||
if (value === '[object Object]') { | ||
// @ts-ignore | ||
var Err = /** @class */ (function () { | ||
function Err(val) { | ||
if (!(this instanceof Err)) { | ||
return new Err(val); | ||
} | ||
this.ok = false; | ||
this.err = true; | ||
this.val = val; | ||
} | ||
Err.prototype[Symbol.iterator] = function () { | ||
return { | ||
next: function () { | ||
return { done: true, value: undefined }; | ||
} | ||
}; | ||
}; | ||
/** | ||
* @deprecated in favor of unwrapOr | ||
* @see unwrapOr | ||
*/ | ||
Err.prototype.else = function (val) { | ||
return val; | ||
}; | ||
Err.prototype.unwrapOr = function (val) { | ||
return val; | ||
}; | ||
Err.prototype.expect = function (msg) { | ||
throw new Error(msg + " - Error: " + toString(this.val)); | ||
}; | ||
Err.prototype.unwrap = function () { | ||
throw new Error("Tried to unwrap Error: " + toString(this.val)); | ||
}; | ||
Err.prototype.map = function (_mapper) { | ||
return this; | ||
}; | ||
Err.prototype.andThen = function (op) { | ||
return this; | ||
}; | ||
Err.prototype.mapErr = function (mapper) { | ||
return new Err(mapper(this.val)); | ||
}; | ||
/** An empty Err */ | ||
Err.EMPTY = new Err(undefined); | ||
return Err; | ||
}()); | ||
exports.Err = Err; | ||
/** | ||
* Contains the success value | ||
*/ | ||
// @ts-ignore | ||
var Ok = /** @class */ (function () { | ||
function Ok(val) { | ||
if (!(this instanceof Ok)) { | ||
return new Ok(val); | ||
} | ||
this.ok = true; | ||
this.err = false; | ||
this.val = val; | ||
} | ||
/** | ||
* Helper function if you know you have an Ok<T> and T is iterable | ||
*/ | ||
Ok.prototype[Symbol.iterator] = function () { | ||
var obj = Object(this.val); | ||
return Symbol.iterator in obj ? obj[Symbol.iterator]() : { | ||
next: function () { | ||
return { done: true, value: undefined }; | ||
} | ||
}; | ||
}; | ||
/** | ||
* @see unwrapOr | ||
* @deprecated in favor of unwrapOr | ||
*/ | ||
Ok.prototype.else = function (_val) { | ||
return this.val; | ||
}; | ||
Ok.prototype.unwrapOr = function (_val) { | ||
return this.val; | ||
}; | ||
Ok.prototype.expect = function (_msg) { | ||
return this.val; | ||
}; | ||
Ok.prototype.unwrap = function () { | ||
return this.val; | ||
}; | ||
Ok.prototype.map = function (mapper) { | ||
return new Ok(mapper(this.val)); | ||
}; | ||
Ok.prototype.andThen = function (mapper) { | ||
return mapper(this.val); | ||
}; | ||
Ok.prototype.mapErr = function (_mapper) { | ||
return this; | ||
}; | ||
/** | ||
* Returns the contained `Ok` value, but never throws. | ||
* Unlike `unwrap()`, this method doesn't throw and is only callable on an Ok<T> | ||
* | ||
* Therefore, it can be used instead of `unwrap()` as a maintainability safeguard | ||
* that will fail to compile if the error type of the Result is later changed to an error that can actually occur. | ||
* | ||
* (this is the `into_ok()` in rust) | ||
*/ | ||
Ok.prototype.safeUnwrap = function () { | ||
return this.val; | ||
}; | ||
Ok.EMPTY = new Ok(undefined); | ||
return Ok; | ||
}()); | ||
exports.Ok = Ok; | ||
var Result; | ||
(function (Result) { | ||
/** | ||
* Parse a set of `Result`s, returning an array of all `Ok` values. | ||
* Short circuits with the first `Err` found, if any | ||
*/ | ||
function all() { | ||
var results = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
results[_i] = arguments[_i]; | ||
} | ||
var okResult = []; | ||
for (var _a = 0, results_1 = results; _a < results_1.length; _a++) { | ||
var result = results_1[_a]; | ||
if (result.ok) { | ||
okResult.push(result.val); | ||
} | ||
else { | ||
return result; | ||
} | ||
} | ||
return new Ok(okResult); | ||
} | ||
Result.all = all; | ||
/** | ||
* Parse a set of `Result`s, short-circuits when an input value is `Ok`. | ||
* If no `Ok` is found, returns an `Err` containing the collected error values | ||
*/ | ||
function any() { | ||
var results = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
results[_i] = arguments[_i]; | ||
} | ||
var errResult = []; | ||
// short-circuits | ||
for (var _a = 0, results_2 = results; _a < results_2.length; _a++) { | ||
var result = results_2[_a]; | ||
if (result.ok) { | ||
return result; | ||
} | ||
else { | ||
errResult.push(result.val); | ||
} | ||
} | ||
// it must be a Err | ||
return new Err(errResult); | ||
} | ||
Result.any = any; | ||
/** | ||
* Wrap an operation that may throw an Error (`try-catch` style) into checked exception style | ||
* @param op The operation function | ||
*/ | ||
function wrap(op) { | ||
try { | ||
value = JSON.stringify(value); | ||
return new Ok(op()); | ||
} | ||
catch (e) { | ||
return new Err(e); | ||
} | ||
} | ||
throw new Error(`${msg} - Error: ${value}`); | ||
} | ||
unwrap() { | ||
let value = this.val.toString(); | ||
if (value === '[object Object]') { | ||
Result.wrap = wrap; | ||
/** | ||
* Wrap an async operation that may throw an Error (`try-catch` style) into checked exception style | ||
* @param op The operation function | ||
*/ | ||
function wrapAsync(op) { | ||
try { | ||
value = JSON.stringify(value); | ||
return op().then(function (val) { return new Ok(val); }).catch(function (e) { return new Err(e); }); | ||
} | ||
catch (e) { | ||
return Promise.resolve(new Err(e)); | ||
} | ||
} | ||
throw new Error(`Tried to unwrap Error: ${value}`); | ||
} | ||
map(mapper) { | ||
return this; | ||
} | ||
mapErr(mapper) { | ||
return new Err(mapper(this.val)); | ||
} | ||
} | ||
Err.EMPTY = new Err(undefined); | ||
export class Ok { | ||
constructor(val) { | ||
this.val = val; | ||
this.ok = true; | ||
this.err = false; | ||
} | ||
/** | ||
* If the result has a value returns that value. Otherwise returns the passed in value. | ||
* @param val the value to replace the error with | ||
*/ | ||
else(val) { | ||
return this.val; | ||
} | ||
expect(msg) { | ||
return this.val; | ||
} | ||
unwrap() { | ||
return this.val; | ||
} | ||
map(mapper) { | ||
return new Ok(mapper(this.val)); | ||
} | ||
mapErr(mapper) { | ||
return this; | ||
} | ||
} | ||
Ok.EMPTY = new Ok(undefined); | ||
export function Results(...results) { | ||
const okResult = []; | ||
for (let result of results) { | ||
if (result.ok) { | ||
okResult.push(result.val); | ||
Result.wrapAsync = wrapAsync; | ||
})(Result = exports.Result || (exports.Result = {})); | ||
function toString(val) { | ||
var value = String(val); | ||
if (value === '[object Object]') { | ||
try { | ||
value = JSON.stringify(val); | ||
} | ||
catch (_a) { | ||
} | ||
} | ||
else { | ||
return new Err(result.val); | ||
} | ||
return value; | ||
} | ||
return new Ok(okResult); | ||
} | ||
var x = Result.all(Ok(3), Err(5)); | ||
}); | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "ts-results", | ||
"version": "2.0.1", | ||
"version": "3.0.0", | ||
"description": "A typescript implementation of Rust's Result object.", | ||
"main": "index.js", | ||
"module": "./esm/index.js", | ||
"types": "index.d.ts", | ||
@@ -7,0 +8,0 @@ "keywords": ["typescript", "rust", "errors", "result"], |
@@ -16,4 +16,7 @@ # ts-results | ||
* [Else](#else) | ||
* [UnwrapOr](#unwrapor) | ||
* [Empty](#empty) | ||
* [Combining Results](#combining-results) | ||
* [Result.all](#result-all) | ||
* [Result.any](#result-any) | ||
* [Usage with rxjs](#usage-with-rxjs) | ||
@@ -36,3 +39,3 @@ * [resultMap](#resultmap) | ||
```bash | ||
$ yarn install ts-results | ||
$ yarn add ts-results | ||
``` | ||
@@ -64,5 +67,5 @@ | ||
if (existsSync(path)) { | ||
return new Ok(readFileSync(path)); | ||
return new Ok(readFileSync(path)); // new is optional here | ||
} else { | ||
return new Err("invalid path"); | ||
return new Err("invalid path"); // new is optional here | ||
} | ||
@@ -84,10 +87,10 @@ } | ||
```typescript | ||
import { Result, Err, Ok, Results } from 'ts-results'; | ||
import { Result, Err, Ok } from 'ts-results'; | ||
``` | ||
#### Creation | ||
```typescript | ||
let okResult: Result<number, Error> = new Ok(10); | ||
let okResult: Result<number, Error> = Ok(10); | ||
let okResult2 = Ok<number, Error>(10); // Exact same as above | ||
let errorResult: Result<number, Error> = new Ok(new Error('bad number!')); | ||
let errorResult: Result<number, Error> = Ok(new Error('bad number!')); | ||
let errorResult2 = Ok<number, Error>(new Error('bad number!')); // Exact same as above | ||
@@ -137,4 +140,4 @@ | ||
```typescript | ||
let goodResult = new Ok(1); | ||
let badResult = new Err(new Error("something went wrong")); | ||
let goodResult = Ok(1); | ||
let badResult = Err(new Error("something went wrong")); | ||
@@ -149,8 +152,11 @@ goodResult.map(num => num + 1).unwrap(); // 2 | ||
#### Else | ||
Deprecated in favor of unwrapOr | ||
#### UnwrapOr | ||
```typescript | ||
let goodResult = new Ok(1); | ||
let badResult = new Err(new Error("something went wrong")); | ||
let goodResult = Ok(1); | ||
let badResult = Err(new Error("something went wrong")); | ||
goodResult.else(5); // 1 | ||
badResult.else(5); // 5 | ||
goodResult.unwrapOr(5); // 1 | ||
badResult.unwrapOr(5); // 5 | ||
``` | ||
@@ -170,5 +176,6 @@ | ||
#### Combining Results | ||
There may be some cases where we have two or more separate `Result` objects and we want to do something with both values. | ||
This is handled by using the `Results` function to combine them. | ||
`ts-results` has two helper functions for operating over n `Result` objects. | ||
##### Result.all | ||
Either returns all of the `Ok` values, or the first `Err` value | ||
```typescript | ||
@@ -178,3 +185,3 @@ let pizzaResult: Result<Pizza, GetPizzaError> = getPizzaSomehow(); | ||
let result = Results(pizzaResult, toppingsResult); // Result<[Pizza, Toppings], GetPizzaError | GetToppingsError> | ||
let result = Result.all(pizzaResult, toppingsResult); // Result<[Pizza, Toppings], GetPizzaError | GetToppingsError> | ||
@@ -184,2 +191,14 @@ let [pizza, toppings] = result.unwrap(); // pizza is a Pizza, toppings is a Toppings. Could throw GetPizzaError or GetToppingsError. | ||
##### Result.any | ||
Either returns the first `Ok` value, or all `Err` values | ||
```typescript | ||
let url1: Result<string, Error1> = attempt1(); | ||
let url2: Result<string, Error2> = attempt2(); | ||
let url3: Result<string, Error3> = attempt3(); | ||
let result = Result.all(url1, url2, url3); // Result<string, Error1 | Error2 | Error3> | ||
let url = result.unwrap(); // At least one attempt gave us a successful url | ||
``` | ||
## Usage with rxjs | ||
@@ -194,3 +213,3 @@ | ||
const obs$: Observable<Result<number, Error>> = of(new Ok(5), new Err('uh oh')); | ||
const obs$: Observable<Result<number, Error>> = of(Ok(5), Err('uh oh')); | ||
@@ -241,3 +260,3 @@ const greaterThanZero = obs$.pipe( | ||
const obs$: Observable<Result<number, Error>> = of(new Ok(5), new Err(new Error('uh oh'))); | ||
const obs$: Observable<Result<number, Error>> = of(Ok(5), Err(new Error('uh oh'))); | ||
@@ -244,0 +263,0 @@ const doubled = obs$.pipe( |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
60277
16
785
360
1