feat: Wrap callback returning Promise for Result utility (#32788)

This commit is contained in:
Sergei Zharinov 2024-11-28 14:07:36 -03:00 committed by GitHub
parent b01dcc78e4
commit baea715bea
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 22 additions and 2 deletions

View file

@ -31,18 +31,29 @@ describe('util/result', () => {
}); });
describe('Wrapping', () => { describe('Wrapping', () => {
it('wraps callback', () => { it('wraps callback returning value', () => {
const res = Result.wrap(() => 42); const res = Result.wrap(() => 42);
expect(res).toEqual(Result.ok(42)); expect(res).toEqual(Result.ok(42));
}); });
it('handles callback error', () => { it('handles throw in callback', () => {
const res = Result.wrap(() => { const res = Result.wrap(() => {
throw 'oops'; throw 'oops';
}); });
expect(res).toEqual(Result.err('oops')); expect(res).toEqual(Result.err('oops'));
}); });
it('wraps callback returning promise', () => {
const res = Result.wrap(() => Promise.resolve(42));
expect(res).toEqual(AsyncResult.ok(42));
});
it('wraps callback returning failed promise', () => {
const err = new Error('unknown');
const res = Result.wrap(() => Promise.reject(err));
expect(res).toEqual(AsyncResult.err(err));
});
it('wraps nullable callback', () => { it('wraps nullable callback', () => {
const res: Result<number, 'oops'> = Result.wrapNullable( const res: Result<number, 'oops'> = Result.wrapNullable(
(): number | null => 42, (): number | null => 42,

View file

@ -142,6 +142,9 @@ export class Result<T extends Val, E extends Val = Error> {
static wrap<T extends Val, E extends Val = Error>( static wrap<T extends Val, E extends Val = Error>(
callback: () => RawValue<T>, callback: () => RawValue<T>,
): Result<T, E>; ): Result<T, E>;
static wrap<T extends Val, E extends Val = Error>(
callback: () => Promise<RawValue<T>>,
): AsyncResult<T, E>;
static wrap<T extends Val, E extends Val = Error, EE extends Val = never>( static wrap<T extends Val, E extends Val = Error, EE extends Val = never>(
promise: Promise<Result<T, EE>>, promise: Promise<Result<T, EE>>,
): AsyncResult<T, E | EE>; ): AsyncResult<T, E | EE>;
@ -157,6 +160,7 @@ export class Result<T extends Val, E extends Val = Error> {
input: input:
| SafeParseReturnType<Input, T> | SafeParseReturnType<Input, T>
| (() => RawValue<T>) | (() => RawValue<T>)
| (() => Promise<RawValue<T>>)
| Promise<Result<T, EE>> | Promise<Result<T, EE>>
| Promise<RawValue<T>>, | Promise<RawValue<T>>,
): Result<T, ZodError<Input>> | Result<T, E | EE> | AsyncResult<T, E | EE> { ): Result<T, ZodError<Input>> | Result<T, E | EE> | AsyncResult<T, E | EE> {
@ -170,6 +174,11 @@ export class Result<T extends Val, E extends Val = Error> {
try { try {
const result = input(); const result = input();
if (result instanceof Promise) {
return AsyncResult.wrap(result);
}
return Result.ok(result); return Result.ok(result);
} catch (error) { } catch (error) {
return Result.err(error); return Result.err(error);