Skip to content

Commit

Permalink
Add non-spread overload for Result.all
Browse files Browse the repository at this point in the history
  • Loading branch information
ConnorSinnott committed Apr 17, 2024
1 parent cb3c471 commit 6141535
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 16 deletions.
25 changes: 25 additions & 0 deletions src/result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -437,9 +437,19 @@ export namespace Result {
* Parse a set of `Result`s, returning an array of all `Ok` values.
* Short circuits with the first `Err` found, if any
*/
export function all<const T extends Result<any, any>[]>(results: T): Result<ResultOkTypes<T>, ResultErrTypes<T>[number]>
export function all<T extends Result<any, any>[]>(
...results: T
): Result<ResultOkTypes<T>, ResultErrTypes<T>[number]>
export function all<T extends Result<any, any>[]>(
arg0: Head<T> | T, ...argN: Tail<T>
): Result<ResultOkTypes<T>, ResultErrTypes<T>[number]> {
const results = arg0 === undefined
? []
: Array.isArray(arg0)
? arg0 as T
: [arg0, ...argN] as T;

const okResult = [];
for (let result of results) {
if (result.isOk()) {
Expand All @@ -456,9 +466,19 @@ export namespace Result {
* 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
*/
export function any<const T extends Result<any, any>[]>(results: T): Result<ResultOkTypes<T>[number], ResultErrTypes<T>>
export function any<T extends Result<any, any>[]>(
...results: T
): Result<ResultOkTypes<T>[number], ResultErrTypes<T>>
export function any<T extends Result<any, any>[]>(
arg0: Head<T> | T, ...argN: Tail<T>
): Result<ResultOkTypes<T>[number], ResultErrTypes<T>> {
const results = arg0 === undefined
? []
: Array.isArray(arg0)
? arg0 as T
: [arg0, ...argN] as T;

const errResult = [];

// short-circuits
Expand Down Expand Up @@ -504,3 +524,8 @@ export namespace Result {
return val instanceof Err || val instanceof Ok;
}
}

// Utility types
type Head<T extends any[]> = T extends [any, ...infer R] ?
T extends [...infer F, ...R] ? F : never : never
type Tail<T extends any[]> = T extends [any, ...infer R] ? R : never
70 changes: 54 additions & 16 deletions test/result.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,20 +110,39 @@ test('Result.all', () => {
expect(all0).toMatchResult(Ok([]));
eq<typeof all0, Result<[], never>>(true);

const all0_array = Result.all([]);
expect(all0_array).toMatchResult(Ok([]));
eq<typeof all0_array, Result<[], never>>(true);

const all1 = Result.all(ok0, ok1);
expect(all1).toMatchResult(Ok([3, true]));
eq<typeof all1, Result<[number, boolean], never>>(true);

const all3 = Result.all(err0, err1);
expect(all3).toMatchResult(Err(err0.error));
eq<typeof all3, Result<[never, never], symbol | Error>>(true);
const all1Array = Result.all([ok0, ok1]);
expect(all1Array).toMatchResult(Ok([3, true]));
eq<typeof all1Array, Result<[number, boolean], never>>(true);

const all2 = Result.all(err0, err1);
expect(all2).toMatchResult(Err(err0.error));
eq<typeof all2, Result<[never, never], symbol | Error>>(true);

const all2Array = Result.all([err0, err1]);
expect(all2Array).toMatchResult(Err(err0.error));
eq<typeof all2Array, Result<[never, never], symbol | Error>>(true);

const all3 = Result.all(...([] as Result<string, number>[]));
eq<typeof all3, Result<string[], number>>(true);

const all3Array = Result.all([] as Result<string, number>[]);
eq<typeof all3Array, Result<string[], number>>(true);

const all4 = Result.all(...([] as Result<string, number>[]));
eq<typeof all4, Result<string[], number>>(true);
const all4 = Result.all(ok0, ok1, ok2, err2);
expect(all4).toMatchResult(Err(9));
eq<typeof all4, Result<[number, boolean, 8, boolean], boolean | 9>>(true);

const all5 = Result.all(ok0, ok1, ok2, err2);
expect(all5).toMatchResult(Err(9));
eq<typeof all5, Result<[number, boolean, 8, boolean], boolean | 9>>(true);
const all4Array = Result.all([ok0, ok1, ok2, err2]);
expect(all4Array).toMatchResult(Err(9));
eq<typeof all4Array, Result<[number, boolean, 8, boolean], boolean | 9>>(true);
});

test('Result.any', () => {
Expand All @@ -138,20 +157,39 @@ test('Result.any', () => {
expect(any0).toMatchResult(Err([]));
eq<typeof any0, Result<never, []>>(true);

const any0Array = Result.any();
expect(any0Array).toMatchResult(Err([]));
eq<typeof any0Array, Result<never, []>>(true);

const any1 = Result.any(ok0, ok1);
expect(any1).toMatchResult(Ok(3));
eq<typeof any1, Result<number | boolean, [never, never]>>(true);

const any3 = Result.any(err0, err1);
expect(any3).toMatchResult(Err([err0.error, err1.error]));
eq<typeof any3, Result<never, [symbol, Error]>>(true);
const any1Array = Result.any([ok0, ok1]);
expect(any1Array).toMatchResult(Ok(3));
eq<typeof any1Array, Result<number | boolean, [never, never]>>(true);

const any2 = Result.any(err0, err1);
expect(any2).toMatchResult(Err([err0.error, err1.error]));
eq<typeof any2, Result<never, [symbol, Error]>>(true);

const any2Array = Result.any([err0, err1]);
expect(any2Array).toMatchResult(Err([err0.error, err1.error]));
eq<typeof any2Array, Result<never, [symbol, Error]>>(true);

const any3 = Result.any(...([] as Result<string, number>[]));
eq<typeof any3, Result<string, number[]>>(true);

const any3Array = Result.any([] as Result<string, number>[]);
eq<typeof any3Array, Result<string, number[]>>(true);

const any4 = Result.any(...([] as Result<string, number>[]));
eq<typeof any4, Result<string, number[]>>(true);
const any4 = Result.any(err0, err1, err2, ok2);
expect(any4).toMatchResult(Ok(8));
eq<typeof any4, Result<boolean | 8, [symbol, Error, 9, boolean]>>(true);

const any5 = Result.any(err0, err1, err2, ok2);
expect(any5).toMatchResult(Ok(8));
eq<typeof any5, Result<boolean | 8, [symbol, Error, 9, boolean]>>(true);
const any4Array = Result.any([err0, err1, err2, ok2]);
expect(any4Array).toMatchResult(Ok(8));
eq<typeof any4Array, Result<boolean | 8, [symbol, Error, 9, boolean]>>(true);
});

test('Result.wrap', () => {
Expand Down

0 comments on commit 6141535

Please sign in to comment.