Skip to content

Commit

Permalink
refactor: Error type narrowing for Result class
Browse files Browse the repository at this point in the history
  • Loading branch information
zharinov committed Nov 24, 2024
1 parent e5655a8 commit 91b1b0f
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 39 deletions.
19 changes: 9 additions & 10 deletions lib/util/result.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,9 +240,8 @@ describe('util/result', () => {
});

it('converts error to Result', () => {
const result = Result.err<string>('oops').catch(() =>
Result.ok<number>(42),
);
const error: Result<number, string> = Result.err<string>('oops');
const result = error.catch((_err) => Result.ok<number>(42));
expect(result).toEqual(Result.ok(42));
});

Expand Down Expand Up @@ -600,15 +599,15 @@ describe('util/result', () => {

describe('Catch', () => {
it('converts error to AsyncResult', async () => {
const result = await Result.err<string>('oops').catch(() =>
AsyncResult.ok(42),
);
const error: Result<number, string> = Result.err<string>('oops');
const result = await error.catch(() => AsyncResult.ok(42));
expect(result).toEqual(Result.ok(42));
});

it('converts error to Promise', async () => {
const fallback = Promise.resolve(Result.ok(42));
const result = await Result.err<string>('oops').catch(() => fallback);
const error: Result<number, string> = Result.err<string>('oops');
const result = await error.catch(() => fallback);
expect(result).toEqual(Result.ok(42));
});

Expand All @@ -619,9 +618,9 @@ describe('util/result', () => {
});

it('converts AsyncResult error to Result', async () => {
const result = await AsyncResult.err<string>('oops').catch(() =>
AsyncResult.ok<number>(42),
);
const error: AsyncResult<number, string> =
AsyncResult.err<string>('oops');
const result = await error.catch(() => AsyncResult.ok<number>(42));
expect(result).toEqual(Result.ok(42));
});
});
Expand Down
51 changes: 22 additions & 29 deletions lib/util/result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -480,28 +480,23 @@ export class Result<T extends Val, E extends Val = Error> {
}

catch<U extends Val = T, EE extends Val = E>(
fn: (err: E) => Result<U, E | EE>,
): Result<T | U, E | EE>;
fn: (err: E) => Result<U, EE>,
): Result<T | U, EE>;
catch<U extends Val = T, EE extends Val = E>(
fn: (err: E) => AsyncResult<U, E | EE>,
): AsyncResult<T | U, E | EE>;
fn: (err: E) => AsyncResult<U, EE>,
): AsyncResult<T | U, EE>;
catch<U extends Val = T, EE extends Val = E>(
fn: (err: E) => Promise<Result<U, E | EE>>,
): AsyncResult<T | U, E | EE>;
fn: (err: E) => Promise<Result<U, EE>>,
): AsyncResult<T | U, EE>;
catch<U extends Val = T, EE extends Val = E>(
fn: (
err: E,
) =>
| Result<U, E | EE>
| AsyncResult<U, E | EE>
| Promise<Result<U, E | EE>>,
): Result<T | U, E | EE> | AsyncResult<T | U, E | EE> {
fn: (err: E) => Result<U, EE> | AsyncResult<U, EE> | Promise<Result<U, EE>>,
): Result<T | U, EE> | AsyncResult<T | U, EE> {
if (this.res.ok) {
return this;
return this as never;
}

if (this.res._uncaught) {
return this;
return this as never;
}

try {
Expand Down Expand Up @@ -833,25 +828,23 @@ export class AsyncResult<T extends Val, E extends Val>
}

catch<U extends Val = T, EE extends Val = E>(
fn: (err: NonNullable<E>) => Result<U, E | EE>,
): AsyncResult<T | U, E | EE>;
fn: (err: NonNullable<E>) => Result<U, EE>,
): AsyncResult<T | U, EE>;
catch<U extends Val = T, EE extends Val = E>(
fn: (err: NonNullable<E>) => AsyncResult<U, E | EE>,
): AsyncResult<T | U, E | EE>;
fn: (err: NonNullable<E>) => AsyncResult<U, EE>,
): AsyncResult<T | U, EE>;
catch<U extends Val = T, EE extends Val = E>(
fn: (err: NonNullable<E>) => Promise<Result<U, E | EE>>,
): AsyncResult<T | U, E | EE>;
fn: (err: NonNullable<E>) => Promise<Result<U, EE>>,
): AsyncResult<T | U, EE>;
catch<U extends Val = T, EE extends Val = E>(
fn: (
err: NonNullable<E>,
) =>
| Result<U, E | EE>
| AsyncResult<U, E | EE>
| Promise<Result<U, E | EE>>,
): AsyncResult<T | U, E | EE> {
const caughtAsyncResult = this.asyncResult.then((result) =>
// eslint-disable-next-line promise/no-nesting
result.catch(fn as never),
) => Result<U, EE> | AsyncResult<U, EE> | Promise<Result<U, EE>>,
): AsyncResult<T | U, EE> {
const caughtAsyncResult: Promise<Result<T, EE>> = this.asyncResult.then(
(result) =>
// eslint-disable-next-line promise/no-nesting
result.catch(fn as never),
);
return AsyncResult.wrap(caughtAsyncResult);
}
Expand Down

0 comments on commit 91b1b0f

Please sign in to comment.