diff --git a/src/dyn.ts b/src/dyn.ts new file mode 100644 index 0000000..b10bf4a --- /dev/null +++ b/src/dyn.ts @@ -0,0 +1,33 @@ +import { None, Option, Some } from "./option.js"; +import { TypeHelpers } from "./typeHelpers.js"; + +export class Dyn { + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- method accepts any value by design + public static cast(variable: any) { + return { + to(type: unknown): Option { + if (TypeHelpers.isNullOrUndefined(variable)) { + throw new Error( + "Invalid 'variable' parameter passed in: null or undefined" + ); + } + if (TypeHelpers.isNullOrUndefined(type)) { + throw new Error( + "Invalid 'type' parameter passed in: null or undefined" + ); + } + + let res: boolean = false; + if (typeof type === "string") { + res = typeof variable === type.toLowerCase(); + } else if (typeof type === "function") { + res = variable.constructor === type; + } + if (res) { + return new Some(variable); + } + return new None(); + }, + }; + } +} diff --git a/src/fpSdk.test.ts b/src/fpSdk.test.ts index 4c57b08..31c317b 100644 --- a/src/fpSdk.test.ts +++ b/src/fpSdk.test.ts @@ -9,6 +9,7 @@ import { Err, Result, TypeHelpers, + Dyn, } from "./index.js"; function typeGuard(option: Option) { @@ -69,76 +70,68 @@ class Bar { } } -test("testing TypeHelpers.IsInstanceOf", () => { +test("testing Dyn.cast.to", () => { const str1 = "foo"; - expect(TypeHelpers.isInstanceOf(str1, String)).toBe(true); + expect(Dyn.cast(str1).to(String).isSome()).toBe(true); const str2 = String("foo"); - expect(TypeHelpers.isInstanceOf(str2, String)).toBe(true); - - //commented this one because prettier complains about it, but it works: - //let str3 = 'foo'; - //expect(TypeHelpers.isInstanceOf(str3, String)).toBe(true); + expect(Dyn.cast(str2).to(String).isSome()).toBe(true); const nonStr = 3; - expect(TypeHelpers.isInstanceOf(nonStr, String)).toBe(false); + expect(Dyn.cast(nonStr).to(String).isSome()).toBe(false); const int1 = 2; - expect(TypeHelpers.isInstanceOf(int1, Number)).toBe(true); + expect(Dyn.cast(int1).to(Number).isSome()).toBe(true); const int2 = Number(2); - expect(TypeHelpers.isInstanceOf(int2, Number)).toBe(true); + expect(Dyn.cast(int2).to(Number).isSome()).toBe(true); const nonInt = "2"; - expect(TypeHelpers.isInstanceOf(nonInt, Number)).toBe(false); + expect(Dyn.cast(nonInt).to(Number).isSome()).toBe(false); const foo = new Foo(); const bar = new Bar(); - expect(TypeHelpers.isInstanceOf(foo, Foo)).toBe(true); - expect(TypeHelpers.isInstanceOf(bar, Bar)).toBe(true); - expect(TypeHelpers.isInstanceOf(foo, Bar)).toBe(false); - expect(TypeHelpers.isInstanceOf(bar, Foo)).toBe(false); + expect(Dyn.cast(foo).to(Foo).isSome()).toBe(true); + expect(Dyn.cast(bar).to(Bar).isSome()).toBe(true); + expect(Dyn.cast(foo).to(Bar).isSome()).toBe(false); + expect(Dyn.cast(bar).to(Foo).isSome()).toBe(false); +}); + +test("testing TypeHelpers.stringIsNullishOrEmpty", () => { + expect(TypeHelpers.stringIsNullishOrEmpty(null as any)).toBe(true); + expect(TypeHelpers.stringIsNullishOrEmpty(undefined as any)).toBe(true); + expect(TypeHelpers.stringIsNullishOrEmpty("")).toBe(true); + expect(TypeHelpers.stringIsNullishOrEmpty("hello")).toBe(false); + expect(TypeHelpers.stringIsNullishOrEmpty(" ")).toBe(false); +}); + +test("testing TypeHelpers.stringIsNullishOrWhiteSpace", () => { + expect(TypeHelpers.stringIsNullishOrWhiteSpace(null as any)).toBe(true); + expect(TypeHelpers.stringIsNullishOrWhiteSpace(undefined as any)).toBe(true); + expect(TypeHelpers.stringIsNullishOrWhiteSpace("")).toBe(true); + expect(TypeHelpers.stringIsNullishOrWhiteSpace(" ")).toBe(true); + expect(TypeHelpers.stringIsNullishOrWhiteSpace("\t")).toBe(true); + expect(TypeHelpers.stringIsNullishOrWhiteSpace("\n")).toBe(true); + expect(TypeHelpers.stringIsNullishOrWhiteSpace(" \t\n ")).toBe(true); + expect(TypeHelpers.stringIsNullishOrWhiteSpace("hello")).toBe(false); + expect(TypeHelpers.stringIsNullishOrWhiteSpace(" hello ")).toBe(false); }); -test("testing TypeHelpers.isInstanceOf exceptions", () => { +test("testing Dyn.cast.to exceptions", () => { const strNull = null; - expect(() => TypeHelpers.isInstanceOf(strNull, String)).toThrowError( - "Invalid" - ); - expect(() => TypeHelpers.isInstanceOf(strNull, String)).toThrowError( - "parameter" - ); - expect(() => TypeHelpers.isInstanceOf(strNull, String)).toThrowError( - "null" - ); + expect(() => Dyn.cast(strNull).to(String)).toThrowError("Invalid"); + expect(() => Dyn.cast(strNull).to(String)).toThrowError("parameter"); + expect(() => Dyn.cast(strNull).to(String)).toThrowError("null"); const strUndefined = undefined; - expect(() => TypeHelpers.isInstanceOf(strUndefined, String)).toThrowError( - "Invalid" - ); - expect(() => TypeHelpers.isInstanceOf(strUndefined, String)).toThrowError( - "parameter" - ); - expect(() => TypeHelpers.isInstanceOf(strUndefined, String)).toThrowError( - "undefined" - ); + expect(() => Dyn.cast(strUndefined).to(String)).toThrowError("Invalid"); + expect(() => Dyn.cast(strUndefined).to(String)).toThrowError("parameter"); + expect(() => Dyn.cast(strUndefined).to(String)).toThrowError("undefined"); const typeNull = null; - expect(() => TypeHelpers.isInstanceOf("foo", typeNull)).toThrowError( - "Invalid" - ); - expect(() => TypeHelpers.isInstanceOf("foo", typeNull)).toThrowError( - "parameter" - ); - expect(() => TypeHelpers.isInstanceOf("foo", typeNull)).toThrowError( - "null" - ); + expect(() => Dyn.cast("foo").to(typeNull)).toThrowError("Invalid"); + expect(() => Dyn.cast("foo").to(typeNull)).toThrowError("parameter"); + expect(() => Dyn.cast("foo").to(typeNull)).toThrowError("null"); const typeUndefined = undefined; - expect(() => TypeHelpers.isInstanceOf("foo", typeUndefined)).toThrowError( - "Invalid" - ); - expect(() => TypeHelpers.isInstanceOf("foo", typeUndefined)).toThrowError( - "parameter" - ); - expect(() => TypeHelpers.isInstanceOf("foo", typeUndefined)).toThrowError( - "undefined" - ); + expect(() => Dyn.cast("foo").to(typeUndefined)).toThrowError("Invalid"); + expect(() => Dyn.cast("foo").to(typeUndefined)).toThrowError("parameter"); + expect(() => Dyn.cast("foo").to(typeUndefined)).toThrowError("undefined"); }); function handleResult(result: Result): string { diff --git a/src/index.ts b/src/index.ts index b79c635..468892b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,5 +8,6 @@ export type { Result } from './result.js'; // Export helpers export { TypeHelpers } from './typeHelpers.js'; +export { Dyn } from './dyn.js'; export { Empty } from './empty.js'; diff --git a/src/typeHelpers.ts b/src/typeHelpers.ts index 9c12e5e..44677be 100644 --- a/src/typeHelpers.ts +++ b/src/typeHelpers.ts @@ -4,26 +4,20 @@ export class TypeHelpers { return variable === null || variable === undefined; } - // because instanceof doesn't work with primitive types (e.g. String), taken from https://stackoverflow.com/a/58184883/544947 - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- method accepts any value by design - public static isInstanceOf(variable: any, type: any) { - if (TypeHelpers.isNullOrUndefined(variable)) { - throw new Error( - "Invalid 'variable' parameter passed in: null or undefined" - ); + public static stringIsNullishOrEmpty(str: string) { + if (TypeHelpers.isNullOrUndefined(str)) { + return true; } - if (TypeHelpers.isNullOrUndefined(type)) { - throw new Error( - "Invalid 'type' parameter passed in: null or undefined" - ); + if (str.length === 0) { + return true; } + return false; + } - let res: boolean = false; - if (typeof type == "string") { - res = typeof variable == type.toLowerCase(); - } else { - res = variable.constructor == type; + public static stringIsNullishOrWhiteSpace(str: string) { + if (TypeHelpers.stringIsNullishOrEmpty(str)) { + return true; } - return res; + return str.trim().length === 0; } }