From ecbee400cb806b20a1e34c200ead09aeca383718 Mon Sep 17 00:00:00 2001
From: Sergei Zharinov <zharinov@users.noreply.github.com>
Date: Tue, 22 Aug 2023 22:40:16 +0300
Subject: [PATCH] feat(result): Add `unwrapOrNull` method (#24025)

---
 lib/util/result.spec.ts | 31 +++++++++++++++++++++++++++++++
 lib/util/result.ts      | 23 +++++++++++++++++++++++
 2 files changed, 54 insertions(+)

diff --git a/lib/util/result.spec.ts b/lib/util/result.spec.ts
index c55d6b0619..74951ee679 100644
--- a/lib/util/result.spec.ts
+++ b/lib/util/result.spec.ts
@@ -159,6 +159,27 @@ describe('util/result', () => {
         const res = Result.err('oops');
         expect(() => res.unwrapOrThrow()).toThrow('oops');
       });
+
+      it('unwrapOrNull returns value for ok-result', () => {
+        const res = Result.ok(42);
+        expect(res.unwrapOrNull()).toBe(42);
+      });
+
+      it('unwrapOrNull returns null for error result', () => {
+        const res = Result.err('oops');
+        expect(res.unwrapOrNull()).toBeNull();
+      });
+
+      it('unwrapOrNull throws uncaught transform error', () => {
+        const res = Result.ok(42);
+        expect(() =>
+          res
+            .transform(() => {
+              throw 'oops';
+            })
+            .unwrapOrNull()
+        ).toThrow('oops');
+      });
     });
 
     describe('Transforming', () => {
@@ -373,6 +394,16 @@ describe('util/result', () => {
         const res = Result.wrap(Promise.reject('oops'));
         await expect(res.unwrapOrThrow()).rejects.toBe('oops');
       });
+
+      it('unwrapOrNull returns value for ok-result', async () => {
+        const res = AsyncResult.ok(42);
+        await expect(res.unwrapOrNull()).resolves.toBe(42);
+      });
+
+      it('unwrapOrNull returns null for error result', async () => {
+        const res = AsyncResult.err('oops');
+        await expect(res.unwrapOrNull()).resolves.toBeNull();
+      });
     });
 
     describe('Transforming', () => {
diff --git a/lib/util/result.ts b/lib/util/result.ts
index aa71a560ab..79ca05709a 100644
--- a/lib/util/result.ts
+++ b/lib/util/result.ts
@@ -362,6 +362,22 @@ export class Result<T extends Val, E extends Val = Error> {
     throw this.res.err;
   }
 
+  /**
+   * Returns the ok-value or `null`.
+   * When error was uncaught during transformation, it's being re-thrown here.
+   */
+  unwrapOrNull(): T | null {
+    if (this.res.ok) {
+      return this.res.val;
+    }
+
+    if (this.res._uncaught) {
+      throw this.res.err;
+    }
+
+    return null;
+  }
+
   /**
    * Transforms the ok-value, sync or async way.
    *
@@ -672,6 +688,13 @@ export class AsyncResult<T extends Val, E extends Val>
     return result.unwrapOrThrow();
   }
 
+  /**
+   * Returns the ok-value or `null`.
+   */
+  unwrapOrNull(): Promise<T | null> {
+    return this.asyncResult.then<T | null>((res) => res.unwrapOrNull());
+  }
+
   /**
    * Transforms the ok-value, sync or async way.
    *
-- 
GitLab