diff --git a/src/lib/util/basic/utility.ts b/src/lib/util/basic/utility.ts index abf01b8..4cdee12 100644 --- a/src/lib/util/basic/utility.ts +++ b/src/lib/util/basic/utility.ts @@ -1,11 +1,171 @@ import { type Either, left, right } from './either' import { none, type Option, some } from './option' -// Pipe function for composition -export const pipe = (a: A, ab: (a: A) => B, bc: (b: B) => C): C => - bc(ab(a)) +interface Pipe { + (value: A): A + (value: A, fn1: (a: A) => B): B + (value: A, fn1: (a: A) => B, fn2: (b: B) => C): C + ( + value: A, + fn1: (a: A) => B, + fn2: (b: B) => C, + fn3: (c: C) => D, + ): D + ( + value: A, + fn1: (a: A) => B, + fn2: (b: B) => C, + fn3: (c: C) => D, + fn4: (d: D) => E, + ): E + ( + value: A, + fn1: (a: A) => B, + fn2: (b: B) => C, + fn3: (c: C) => D, + fn4: (d: D) => E, + fn5: (e: E) => F, + ): F + ( + value: A, + fn1: (a: A) => B, + fn2: (b: B) => C, + fn3: (c: C) => D, + fn4: (d: D) => E, + fn5: (e: E) => F, + fn6: (f: F) => G, + ): G + ( + value: A, + fn1: (a: A) => B, + fn2: (b: B) => C, + fn3: (c: C) => D, + fn4: (d: D) => E, + fn5: (e: E) => F, + fn6: (f: F) => G, + fn7: (g: G) => H, + ): H + ( + value: A, + fn1: (a: A) => B, + fn2: (b: B) => C, + fn3: (c: C) => D, + fn4: (d: D) => E, + fn5: (e: E) => F, + fn6: (f: F) => G, + fn7: (g: G) => H, + fn8: (h: H) => I, + ): I + ( + value: A, + fn1: (a: A) => B, + fn2: (b: B) => C, + fn3: (c: C) => D, + fn4: (d: D) => E, + fn5: (e: E) => F, + fn6: (f: F) => G, + fn7: (g: G) => H, + fn8: (h: H) => I, + fn9: (i: I) => J, + ): J + ( + value: A, + fn1: (a: A) => B, + fn2: (b: B) => C, + fn3: (c: C) => D, + fn4: (d: D) => E, + fn5: (e: E) => F, + fn6: (f: F) => G, + fn7: (g: G) => H, + fn8: (h: H) => I, + fn9: (i: I) => J, + fn10: (j: J) => K, + ): K +} + +export const pipe: Pipe = (value: unknown, ...fns: Function[]): unknown => { + return fns.reduce((acc, fn) => fn(acc), value) +} + +// Compose Function (reverse order) +interface Compose { + (): (a: A) => A + (fn1: (a: A) => B): (a: A) => B + (fn2: (b: B) => C, fn1: (a: A) => B): (a: A) => C + ( + fn3: (c: C) => D, + fn2: (b: B) => C, + fn1: (a: A) => B, + ): (a: A) => D + ( + fn4: (d: D) => E, + fn3: (c: C) => D, + fn2: (b: B) => C, + fn1: (a: A) => B, + ): (a: A) => E + ( + fn5: (e: E) => F, + fn4: (d: D) => E, + fn3: (c: C) => D, + fn2: (b: B) => C, + fn1: (a: A) => B, + ): (a: A) => F + ( + fn6: (f: F) => G, + fn5: (e: E) => F, + fn4: (d: D) => E, + fn3: (c: C) => D, + fn2: (b: B) => C, + fn1: (a: A) => B, + ): (a: A) => G + ( + fn7: (g: G) => H, + fn6: (f: F) => G, + fn5: (e: E) => F, + fn4: (d: D) => E, + fn3: (c: C) => D, + fn2: (b: B) => C, + fn1: (a: A) => B, + ): (a: A) => H + ( + fn8: (h: H) => I, + fn7: (g: G) => H, + fn6: (f: F) => G, + fn5: (e: E) => F, + fn4: (d: D) => E, + fn3: (c: C) => D, + fn2: (b: B) => C, + fn1: (a: A) => B, + ): (a: A) => I + ( + fn9: (i: I) => J, + fn8: (h: H) => I, + fn7: (g: G) => H, + fn6: (f: F) => G, + fn5: (e: E) => F, + fn4: (d: D) => E, + fn3: (c: C) => D, + fn2: (b: B) => C, + fn1: (a: A) => B, + ): (a: A) => J + ( + fn10: (j: J) => K, + fn9: (i: I) => J, + fn8: (h: H) => I, + fn7: (g: G) => H, + fn6: (f: F) => G, + fn5: (e: E) => F, + fn4: (d: D) => E, + fn3: (c: C) => D, + fn2: (b: B) => C, + fn1: (a: A) => B, + ): (a: A) => K +} + +export const compose: Compose = (...fns: Function[]) => { + return (value: unknown) => fns.reduceRight((acc, fn) => fn(acc), value) +} -// TryCatch helper using Either export const tryCatch = (f: () => A): Either => { try { return right(f()) @@ -14,6 +174,5 @@ export const tryCatch = (f: () => A): Either => { } } -// Option from nullable export const fromNullable = (a: A | null | undefined): Option => a == null ? none : some(a)