Skip to content

Commit

Permalink
Merge pull request #483 from braxtonhall/fix-combine-with-all-errors
Browse files Browse the repository at this point in the history
Fix combineWithAllErrors types
  • Loading branch information
supermacro authored Aug 28, 2024
2 parents e72e9cd + ecc25b9 commit 5121236
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 34 deletions.
5 changes: 5 additions & 0 deletions .changeset/thirty-grapes-drum.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"neverthrow": patch
---

Fix `combineWithAllErrors` types
21 changes: 6 additions & 15 deletions src/result-async.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,22 +278,13 @@ type TraverseAsync<T, Depth extends number = 5> = IsLiteralArray<T> extends 1
: never

// This type is similar to the `TraverseAsync` while the errors are also
// collected in order. For the checks/conditions made here, see that type
// collected in a list. For the checks/conditions made here, see that type
// for the documentation.
type TraverseWithAllErrorsAsync<T, Depth extends number = 5> = IsLiteralArray<T> extends 1
? Combine<T, Depth> extends [infer Oks, infer Errs]
? ResultAsync<EmptyArrayToNever<Oks>, EmptyArrayToNever<Errs>>
: never
: Writable<T> extends Array<infer I>
? Combine<MemberListOf<I>, Depth> extends [infer Oks, infer Errs]
? Oks extends unknown[]
? Errs extends unknown[]
? ResultAsync<EmptyArrayToNever<Oks[number][]>, EmptyArrayToNever<Errs[number][]>>
: ResultAsync<EmptyArrayToNever<Oks[number][]>, Errs>
: Errs extends unknown[]
? ResultAsync<Oks, EmptyArrayToNever<Errs[number][]>>
: ResultAsync<Oks, Errs>
: never
type TraverseWithAllErrorsAsync<T, Depth extends number = 5> = TraverseAsync<
T,
Depth
> extends ResultAsync<infer Oks, infer Errs>
? ResultAsync<Oks, Errs[]>
: never

// Converts a reaodnly array into a writable array
Expand Down
8 changes: 4 additions & 4 deletions src/result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -649,11 +649,11 @@ type Traverse<T, Depth extends number = 5> = Combine<T, Depth> extends [infer Ok

// Traverses an array of results and returns a single result containing
// the oks combined and the array of errors combined.
type TraverseWithAllErrors<T, Depth extends number = 5> = Combine<T, Depth> extends [
type TraverseWithAllErrors<T, Depth extends number = 5> = Traverse<T, Depth> extends Result<
infer Oks,
infer Errs,
]
? Result<EmptyArrayToNever<Oks>, EmptyArrayToNever<Errs>>
infer Errs
>
? Result<Oks, Errs[]>
: never

// Combines the array of results into one result.
Expand Down
2 changes: 1 addition & 1 deletion tests/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -711,7 +711,7 @@ describe('Utils', () => {
okAsync(true),
]

type ExpecteResult = Result<[ string, number, boolean ], [string, number, boolean]>
type ExpecteResult = Result<[ string, number, boolean ], (string | number | boolean)[]>

const result: ExpecteResult = await ResultAsync.combineWithAllErrors(heterogenousList)

Expand Down
48 changes: 34 additions & 14 deletions tests/typecheck-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1177,7 +1177,7 @@ type CreateTuple<L, V = string> =

(function describe(_ = 'combineWithAllErrors') {
(function it(_ = 'combines different results into one') {
type Expectation = Result<[ number, string, never, never ], [never, never, string[], Error]>;
type Expectation = Result<[ number, string, never, never ], (string[] | Error)[]>;

const result = Result.combineWithAllErrors([
ok(1),
Expand All @@ -1191,7 +1191,7 @@ type CreateTuple<L, V = string> =
});

(function it(_ = 'combines only ok results into one') {
type Expectation = Result<[ number, string ], [never, never]>;
type Expectation = Result<[ number, string ], never[]>;

const result = Result.combineWithAllErrors([
ok(1),
Expand All @@ -1203,7 +1203,7 @@ type CreateTuple<L, V = string> =
});

(function it(_ = 'combines only err results into one') {
type Expectation = Result<[ never, never ], [number, 'string']>;
type Expectation = Result<[ never, never ], (number | 'string')[]>;

const result = Result.combineWithAllErrors([
err(1),
Expand All @@ -1224,10 +1224,20 @@ type CreateTuple<L, V = string> =
const assignablefromCheck: typeof result = assignableToCheck;
});

(function it(_ = 'combines arrays of different results to a result of an array') {
type Expectation = Result<(string | boolean)[], (number | string)[]>;
const results: (Result<string, number> | Result<boolean, string>)[] = [];

const result = Result.combineWithAllErrors(results);

const assignableToCheck: Expectation = result;
const assignablefromCheck: typeof result = assignableToCheck;
});

(function describe(_ = 'inference on large tuples') {
(function it(_ = 'Should correctly infer the type on tuples with 6 elements') {
type Input = CreateTuple<6, Result<string, number>>
type Expectation = Result<CreateTuple<6, string>, CreateTuple<6, number>>
type Expectation = Result<CreateTuple<6, string>, number[]>

const inputValues = input<Input>()
const result = Result.combineWithAllErrors(inputValues)
Expand All @@ -1239,7 +1249,7 @@ type CreateTuple<L, V = string> =

(function it(_ = 'Should correctly infer the type on tuples with 15 elements') {
type Input = CreateTuple<15, Result<string, number>>
type Expectation = Result<CreateTuple<15, string>, CreateTuple<15, number>>
type Expectation = Result<CreateTuple<15, string>, number[]>

const inputValues = input<Input>()
const result = Result.combineWithAllErrors(inputValues)
Expand All @@ -1251,7 +1261,7 @@ type CreateTuple<L, V = string> =

(function it(_ = 'Should correctly infer the type on tuples with 30 elements') {
type Input = CreateTuple<30, Result<string, number>>
type Expectation = Result<CreateTuple<30, string>, CreateTuple<30, number>>
type Expectation = Result<CreateTuple<30, string>, number[]>

const inputValues = input<Input>()
const result = Result.combineWithAllErrors(inputValues)
Expand All @@ -1263,7 +1273,7 @@ type CreateTuple<L, V = string> =

(function it(_ = 'Should correctly infer the type on tuples with 49 elements') {
type Input = CreateTuple<49 , Result<string, number>>
type Expectation = Result<CreateTuple<49, string>, CreateTuple<49, number>>
type Expectation = Result<CreateTuple<49, string>, number[]>

const inputValues = input<Input>()
const result = Result.combineWithAllErrors(inputValues)
Expand Down Expand Up @@ -2199,7 +2209,7 @@ type CreateTuple<L, V = string> =

(function describe(_ = 'combineWithAllErrors') {
(function it(_ = 'combines different result asyncs into one') {
type Expectation = ResultAsync<[ number, string, never, never ], [never, never, string[], Error]>;
type Expectation = ResultAsync<[ number, string, never, never ], (string[] | Error)[]>;

const result = ResultAsync.combineWithAllErrors([
okAsync(1),
Expand All @@ -2213,7 +2223,7 @@ type CreateTuple<L, V = string> =
});

(function it(_ = 'combines only ok result asyncs into one') {
type Expectation = ResultAsync<[ number, string ], [never, never]>;
type Expectation = ResultAsync<[ number, string ], never[]>;

const result = ResultAsync.combineWithAllErrors([
okAsync(1),
Expand All @@ -2225,7 +2235,7 @@ type CreateTuple<L, V = string> =
});

(function it(_ = 'combines only err result asyncs into one') {
type Expectation = ResultAsync<[ never, never ], [number, string]>;
type Expectation = ResultAsync<[ never, never ], (number | string)[]>;

const result = ResultAsync.combineWithAllErrors([
errAsync(1),
Expand All @@ -2246,10 +2256,20 @@ type CreateTuple<L, V = string> =
const assignablefromCheck: typeof result = assignableToCheck;
});

(function it(_ = 'combines arrays of different result asyncs to a result of an array') {
type Expectation = ResultAsync<(string | boolean)[], (number | string)[]>;
const results: (ResultAsync<string, number> | ResultAsync<boolean, string>)[] = [];

const result = ResultAsync.combineWithAllErrors(results);

const assignableToCheck: Expectation = result;
const assignablefromCheck: typeof result = assignableToCheck;
});

(function describe(_ = 'inference on large tuples') {
(function it(_ = 'Should correctly infer the type on tuples with 6 elements') {
type Input = CreateTuple<6, ResultAsync<string, number>>
type Expectation = ResultAsync<CreateTuple<6, string>, CreateTuple<6, number>>
type Expectation = ResultAsync<CreateTuple<6, string>, number[]>

const inputValues = input<Input>()
const result = ResultAsync.combineWithAllErrors(inputValues)
Expand All @@ -2261,7 +2281,7 @@ type CreateTuple<L, V = string> =

(function it(_ = 'Should correctly infer the type on tuples with 15 elements') {
type Input = CreateTuple<15, ResultAsync<string, number>>
type Expectation = ResultAsync<CreateTuple<15, string>, CreateTuple<15, number>>
type Expectation = ResultAsync<CreateTuple<15, string>, number[]>

const inputValues = input<Input>()
const result = ResultAsync.combineWithAllErrors(inputValues)
Expand All @@ -2273,7 +2293,7 @@ type CreateTuple<L, V = string> =

(function it(_ = 'Should correctly infer the type on tuples with 30 elements') {
type Input = CreateTuple<30, ResultAsync<string, number>>
type Expectation = ResultAsync<CreateTuple<30, string>, CreateTuple<30, number>>
type Expectation = ResultAsync<CreateTuple<30, string>, number[]>

const inputValues = input<Input>()
const result = ResultAsync.combineWithAllErrors(inputValues)
Expand All @@ -2285,7 +2305,7 @@ type CreateTuple<L, V = string> =

(function it(_ = 'Should correctly infer the type on tuples with 49 elements') {
type Input = CreateTuple<49 , ResultAsync<string, number>>
type Expectation = ResultAsync<CreateTuple<49, string>, CreateTuple<49, number>>
type Expectation = ResultAsync<CreateTuple<49, string>, number[]>

const inputValues = input<Input>()
const result = ResultAsync.combineWithAllErrors(inputValues)
Expand Down

0 comments on commit 5121236

Please sign in to comment.