From c34b54d166b6de284ead416f8a92e26718cfb200 Mon Sep 17 00:00:00 2001 From: Devin Bidwell Date: Tue, 2 Sep 2025 11:31:00 -0700 Subject: [PATCH 1/4] Added unsafe option utils to return raw values unchecked --- src/option/index.ts | 20 ++++++++++++++++++++ src/option/option.test.ts | 12 ++++++++++++ 2 files changed, 32 insertions(+) diff --git a/src/option/index.ts b/src/option/index.ts index e92e499..c79b641 100644 --- a/src/option/index.ts +++ b/src/option/index.ts @@ -51,6 +51,11 @@ export interface OptionUtils { * @returns The value of the `Option`. */ unwrap(): T; + /** + * Extracts the base value from this type, not checking if the value is `None`. + * @returns The raw unchecked inner value of the `Option` + */ + unsafeUnwrap(): T | null | undefined; /** * Extracts the base value from this type. If there is no value in the `Option`, the function will return the provided default value. * @param defaultValue The value to return if the `Option` is a `None`. @@ -58,6 +63,13 @@ export interface OptionUtils { * @returns The value of the `Option` if it is a `Some`, otherwise the default value. */ unwrapOr(defaultValue: T): T; + /** + * Extracts the base value from this type. If there is no value in the `Option`, the function will return whatever you provided as the + * default value, even if that value was not provided (undefined). + * @param defaultValue The value to return if the `Option` is a `None` + * @returns The possibly undefined | null value of the `Option`. + */ + unsafeUnwrapOr(defaultValue?: T | null): T | null | undefined; /** * Extracts the base value from this type. The function throws an error with the provided message if there is no value provided. * @throws {OptionIsEmptyError} if the default value is `null` or `undefined`. @@ -114,6 +126,10 @@ function buildOption(innerType: Some | None): Option { if (this.isNone()) throw new OptionIsEmptyError(); return this.value; }, + unsafeUnwrap() { + if (this.isNone()) return undefined; + return this.value; + }, unwrapOr(defaultValue) { if (this.isSome()) return this.value; if (defaultValue === null || defaultValue === undefined) @@ -122,6 +138,10 @@ function buildOption(innerType: Some | None): Option { ); return defaultValue; }, + unsafeUnwrapOr(defaultValue) { + if (this.isNone()) return defaultValue; + return this.value; + }, expect(message) { if (this.isSome()) return this.value; throw new OptionIsEmptyError(message); diff --git a/src/option/option.test.ts b/src/option/option.test.ts index 6bd0297..f12fedf 100644 --- a/src/option/option.test.ts +++ b/src/option/option.test.ts @@ -185,4 +185,16 @@ describe("src/utility/option.ts", () => { ])("Properly checks the return type of %s", (_, optVal, validator) => { expect(validator(optVal)).toBeTruthy(); }); + + it("Returns `undefined` if unsafeUnwrap() was called on a None type", () => { + const opt = option.unknown(undefined); + + expect(opt.unsafeUnwrap()).toEqual(undefined); + }); + + it("returns the raw default value if unsafeUnwrapOr() was called on a None type", () => { + const opt = option.unknown(undefined); + + expect(opt.unsafeUnwrapOr(null)).toEqual(null); + }); }); From ce42c97ac712fb219f389423b5650012bbbb200a Mon Sep 17 00:00:00 2001 From: Devin Bidwell Date: Tue, 2 Sep 2025 11:31:35 -0700 Subject: [PATCH 2/4] 1.1.0 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 393e104..e630eab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@dbidwell94/ts-utils", - "version": "1.0.0", + "version": "1.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@dbidwell94/ts-utils", - "version": "1.0.0", + "version": "1.1.0", "license": "MIT", "devDependencies": { "@types/jest": "^30.0.0", diff --git a/package.json b/package.json index a0e565b..ad6bdb1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@dbidwell94/ts-utils", - "version": "1.0.0", + "version": "1.1.0", "description": "A collection of helpful TypeScript utilities with the aim of having limited production dependencies.", "main": "dist/index.js", "files": [ From acc39efe14bc29c9dbc51c3dd1d1e8f3376232bb Mon Sep 17 00:00:00 2001 From: Devin Bidwell Date: Tue, 2 Sep 2025 11:33:32 -0700 Subject: [PATCH 3/4] update changelog and minor version bump --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a596ee8..314fd2a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [1.1.0] + +- Added new unsafe functions to the `Option` type to return unchecked values. + - unsafeUnwrap() -- Returns the inner value regardless on if it is `undefined` + or `null` + - unsafeUnwrapOr() -- Maps the inner value to an optional default value + without checking the default value for `null | undefined` + ## [1.0.0] - Removed multiple named exports from the base library in favor of From 631dd1a424cbc69ffa1ea8cdc84052d35ff2a92c Mon Sep 17 00:00:00 2001 From: Devin Bidwell Date: Tue, 2 Sep 2025 11:39:16 -0700 Subject: [PATCH 4/4] Added more tests --- src/option/option.test.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/option/option.test.ts b/src/option/option.test.ts index f12fedf..c4a11b6 100644 --- a/src/option/option.test.ts +++ b/src/option/option.test.ts @@ -192,9 +192,21 @@ describe("src/utility/option.ts", () => { expect(opt.unsafeUnwrap()).toEqual(undefined); }); + it("Returns the inner value of Some if unsafeUnwrap was called on a Some type", () => { + const opt = option.some(123); + + expect(opt.unsafeUnwrap()).toEqual(123); + }); + it("returns the raw default value if unsafeUnwrapOr() was called on a None type", () => { const opt = option.unknown(undefined); expect(opt.unsafeUnwrapOr(null)).toEqual(null); }); + + it("Returns the inner value of Some if unsafeUnwrapOr() was called on a Some type", () => { + const opt = option.some(123); + + expect(opt.unsafeUnwrapOr(null)).toEqual(123); + }); });