Skip to content

Commit

Permalink
feat(result): Extend wrapNullable to accept pure values (#23978)
Browse files Browse the repository at this point in the history
  • Loading branch information
zharinov committed Aug 21, 2023
1 parent 745edc1 commit be8a9f7
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 25 deletions.
15 changes: 15 additions & 0 deletions lib/util/result.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,21 @@ describe('util/result', () => {
expect(res).toEqual(Result.err('oops'));
});

it('wraps pure nullable value', () => {
const res = Result.wrapNullable(42, 'oops');

This comment has been minimized.

Copy link
@Giangpro89

Giangpro89 Aug 21, 2023

Coin res

expect(res).toEqual(Result.ok(42));
});

it('wraps nullable value null', () => {
const res = Result.wrapNullable(null, 'oops');
expect(res).toEqual(Result.err('oops'));
});

it('wraps nullable value undefined', () => {
const res = Result.wrapNullable(undefined, 'oops');
expect(res).toEqual(Result.err('oops'));
});

it('wraps zod parse result', () => {
const schema = z.string().transform((x) => x.toUpperCase());
expect(Result.wrap(schema.safeParse('foo'))).toEqual(Result.ok('FOO'));
Expand Down
73 changes: 48 additions & 25 deletions lib/util/result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,26 @@ type RawValue<T extends Val> = Exclude<
SafeParseReturnType<unknown, T> | Promise<unknown>
>;

function fromNullable<
T extends Val,
ErrForNull extends Val,
ErrForUndefined extends Val
>(
input: Nullable<T>,
errForNull: ErrForNull,
errForUndefined: ErrForUndefined
): Result<T, ErrForNull | ErrForUndefined> {
if (input === null) {
return Result.err(errForNull);
}

if (input === undefined) {
return Result.err(errForUndefined);
}

return Result.ok(input);
}

/**
* Class for representing a result that can fail.
*
Expand Down Expand Up @@ -243,13 +263,31 @@ export class Result<T extends Val, E extends Val = Error> {
errForNull: ErrForNull,
errForUndefined: ErrForUndefined
): AsyncResult<T, E | ErrForNull | ErrForUndefined>;
static wrapNullable<
T extends Val,
E extends Val = Error,
ErrForNullable extends Val = Error
>(
value: Nullable<T>,
errForNullable: ErrForNullable
): Result<T, E | ErrForNullable>;
static wrapNullable<
T extends Val,
E extends Val = Error,
ErrForNull extends Val = Error,
ErrForUndefined extends Val = Error
>(
input: (() => Nullable<T>) | Promise<Nullable<T>>,
value: Nullable<T>,
errForNull: ErrForNull,
errForUndefined: ErrForUndefined
): Result<T, E | ErrForNull | ErrForUndefined>;
static wrapNullable<
T extends Val,
E extends Val = Error,
ErrForNull extends Val = Error,
ErrForUndefined extends Val = Error
>(
input: (() => Nullable<T>) | Promise<Nullable<T>> | Nullable<T>,
arg2: ErrForNull,
arg3?: ErrForUndefined
):
Expand All @@ -262,21 +300,16 @@ export class Result<T extends Val, E extends Val = Error> {
return AsyncResult.wrapNullable(input, errForNull, errForUndefined);
}

try {
const result = input();

if (result === null) {
return Result.err(errForNull);
if (input instanceof Function) {
try {
const result = input();
return fromNullable(result, errForNull, errForUndefined);
} catch (error) {
return Result.err(error);
}

if (result === undefined) {
return Result.err(errForUndefined);
}

return Result.ok(result);
} catch (error) {
return Result.err(error);
}

return fromNullable(input, errForNull, errForUndefined);
}

/**
Expand Down Expand Up @@ -564,17 +597,7 @@ export class AsyncResult<T extends Val, E extends Val>
): AsyncResult<T, E | ErrForNull | ErrForUndefined> {
return new AsyncResult(
promise
.then((value) => {
if (value === null) {
return Result.err(errForNull);
}

if (value === undefined) {
return Result.err(errForUndefined);
}

return Result.ok(value);
})
.then((value) => fromNullable(value, errForNull, errForUndefined))
.catch((err) => Result.err(err))
);
}
Expand Down

0 comments on commit be8a9f7

Please sign in to comment.