Repository: karen-irc/option-t
Pull request #1472 (2022-11-20 12:35:53)

Implement `unwrapOrThrowErrorFromResult()`


Patch:
diff --git a/docs/public_api_list.md b/docs/public_api_list.md
index 82af9a7a..0c4516ac 100644
--- a/docs/public_api_list.md
+++ b/docs/public_api_list.md
@@ -129,6 +129,7 @@
 - [option-t/PlainResult/unwrapOr](../src/PlainResult/unwrapOr.ts)
 - [option-t/PlainResult/unwrapOrElse](../src/PlainResult/unwrapOrElse.ts)
 - [option-t/PlainResult/unwrapOrElseAsync](../src/PlainResult/unwrapOrElseAsync.ts)
+- [option-t/PlainResult/unwrapOrThrowError](../src/PlainResult/unwrapOrThrowError.ts)
 
 
 ## Undefinable
diff --git a/src/PlainResult/unwrapOrThrowError.ts b/src/PlainResult/unwrapOrThrowError.ts
new file mode 100644
index 00000000..811e1f0f
--- /dev/null
+++ b/src/PlainResult/unwrapOrThrowError.ts
@@ -0,0 +1,33 @@
+import { type Result, isOk } from './Result.js';
+import { unwrapErrFromResult, unwrapOkFromResult } from './unwrap.js';
+
+/**
+ *  Unwraps _input_, returns the content of an `Ok(T)`.
+ *  Otherwise, this function throw the contained `Error` in `Err(Error)`.
+ *
+ *  @deprecated
+ *  This function is marked as _deprecated_ as meaning of __not recommend to use__.
+ *
+ *  This marking displays this function usages with strikethrough line decolation on an editor.
+ *
+ *  This function is provided only to improve an interoperability with the world using "throw error" convention.
+ *  __We do not recommend to use this function__.
+ */
+export function unwrapOrThrowErrorFromResult<T>(input: Result<T, Error>): T {
+    if (isOk(input)) {
+        const val: T = unwrapOkFromResult<T>(input);
+        return val;
+    }
+
+    const e: unknown = unwrapErrFromResult(input);
+    if (!(e instanceof Error)) {
+        throw new TypeError(
+            `The contained E should be \`Error\` instance but that was \`${String(e)}\``,
+            {
+                cause: e,
+            }
+        );
+    }
+
+    throw e;
+}
diff --git a/tools/pkg_files.json b/tools/pkg_files.json
index cfb6beec..4a5d7e84 100644
--- a/tools/pkg_files.json
+++ b/tools/pkg_files.json
@@ -237,6 +237,8 @@
     "cjs/PlainResult/unwrapOrElse.cjs": null,
     "cjs/PlainResult/unwrapOrElseAsync.d.ts": null,
     "cjs/PlainResult/unwrapOrElseAsync.cjs": null,
+    "cjs/PlainResult/unwrapOrThrowError.d.ts": null,
+    "cjs/PlainResult/unwrapOrThrowError.cjs": null,
     "cjs/Result.d.ts": null,
     "cjs/Result.cjs": null,
     "cjs/Undefinable/ErrorMessage.d.ts": null,
@@ -528,6 +530,8 @@
     "esm/PlainResult/unwrapOrElse.mjs": null,
     "esm/PlainResult/unwrapOrElseAsync.d.ts": null,
     "esm/PlainResult/unwrapOrElseAsync.mjs": null,
+    "esm/PlainResult/unwrapOrThrowError.d.ts": null,
+    "esm/PlainResult/unwrapOrThrowError.mjs": null,
     "esm/Result.d.ts": null,
     "esm/Result.mjs": null,
     "esm/Undefinable/ErrorMessage.d.ts": null,
@@ -695,6 +699,7 @@
     "lib/PlainResult/unwrapOr.d.ts": null,
     "lib/PlainResult/unwrapOrElse.d.ts": null,
     "lib/PlainResult/unwrapOrElseAsync.d.ts": null,
+    "lib/PlainResult/unwrapOrThrowError.d.ts": null,
     "lib/Result.d.ts": null,
     "lib/Undefinable/ErrorMessage.d.ts": null,
     "lib/Undefinable/Undefinable.d.ts": null,
diff --git a/tools/public_api/table.mjs b/tools/public_api/table.mjs
index 4cd93715..073701b1 100644
--- a/tools/public_api/table.mjs
+++ b/tools/public_api/table.mjs
@@ -663,6 +663,11 @@ export const apiTable = Object.freeze({
             'unwrapOrElseAsyncFromResult'
         ]
     },
+    'PlainResult/unwrapOrThrowError': {
+        'exports': [
+            'unwrapOrThrowErrorFromResult'
+        ]
+    },
 
     'Undefinable': {
         'path': 'Undefinable/index',
diff --git a/tsconfig.base.json b/tsconfig.base.json
index be44fcdd..380ae9f2 100644
--- a/tsconfig.base.json
+++ b/tsconfig.base.json
@@ -8,7 +8,8 @@
         "module": "es2015",                           /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
         "lib": [                                   /* Specify library files to be included in the compilation. */
             "ES5",
-            "ES2015.Promise"
+            "ES2015.Promise",
+            "ES2022.Error",
         ],
         // "allowJs": true,                             /* Allow javascript files to be compiled. */
         // "checkJs": true,                             /* Report errors in .js files. */


Test patch:
diff --git a/__tests__/PlainResult/unwrap_or_throw_error.test.mjs b/__tests__/PlainResult/unwrap_or_throw_error.test.mjs
new file mode 100644
index 00000000..d57529eb
--- /dev/null
+++ b/__tests__/PlainResult/unwrap_or_throw_error.test.mjs
@@ -0,0 +1,51 @@
+import test from 'ava';
+import { webcrypto } from 'node:crypto';
+
+import { createOk, createErr } from '../../__dist/esm/PlainResult/Result.mjs';
+import { unwrapOrThrowErrorFromResult } from '../../__dist/esm/PlainResult/unwrapOrThrowError.mjs';
+
+test('input is Ok(T)', (t) => {
+    const VALUE_T = Math.random();
+
+    const input = createOk(VALUE_T);
+    let actual;
+    t.notThrows(() => {
+        actual = unwrapOrThrowErrorFromResult(input);
+    });
+    t.is(actual, VALUE_T);
+});
+
+test('input is Err(Error)', (t) => {
+    const ERROR_E = new Error();
+
+    const input = createErr(ERROR_E);
+    t.throws(
+        () => {
+            unwrapOrThrowErrorFromResult(input);
+        },
+        {
+            is: ERROR_E,
+        }
+    );
+});
+
+test('input is Err, but the contained value is not Error', (t) => {
+    t.plan(2);
+
+    const ERROR_E = webcrypto.randomUUID();
+
+    const input = createErr(ERROR_E);
+    const thrown = t.throws(
+        () => {
+            unwrapOrThrowErrorFromResult(input);
+        },
+        {
+            instanceOf: TypeError,
+            message: `The contained E should be \`Error\` instance but that was \`${String(
+                ERROR_E
+            )}\``,
+        }
+    );
+
+    t.is(thrown.cause, ERROR_E, `should be set Error.cause`);
+});