Repository: marpple/FxTS
Pull request #149 (2022-03-31 08:00:04)

Fix/unicode
Fixes https://github.com/marpple/FxTS/issues/148

Instead of handling unicode with the `Array.from` function in dropRight (and reverse, takeRight), the `unicodeToArray` function of `lodash.js` is provided, so that the user can directly process the unicode as needed.

hg-pyun: @shine1594 
I don't know if FxTS should provide this function. I think I can definitely use it from the outside...
ppeeou: > @shine1594 Additionally, I don't know if FxTS should provide this function. I think I can definitely use it from the outside...

@hg-pyun 
Do you mean by using  `unicodeToArray` if a `string` value is entered in an operation like `toArray`? without exposing the function?

Patch:
diff --git a/src/Lazy/dropRight.ts b/src/Lazy/dropRight.ts
index 0374a245..5bcf5e0e 100644
--- a/src/Lazy/dropRight.ts
+++ b/src/Lazy/dropRight.ts
@@ -5,21 +5,9 @@ import ReturnIterableIteratorType from "../types/ReturnIterableIteratorType";
 import { isAsyncIterable, isIterable } from "../_internal/utils";
 import concurrent, { isConcurrent } from "./concurrent";
 
-function* stringDropRight(length: number, str: string) {
-  const arr = Array.from(str);
-  for (let i = 0; i < str.length - length; i++) {
-    yield arr[i];
-  }
-}
-
-function* arrayDropRight<T>(length: number, arr: Array<T>) {
-  for (let i = 0; i < arr.length - length; i++) {
-    yield arr[i];
-  }
-}
-
 function* sync<T>(length: number, iterable: Iterable<T>) {
-  const arr = toArray(iterable);
+  const arr =
+    isArray(iterable) || isString(iterable) ? iterable : toArray(iterable);
   for (let i = 0; i < arr.length - length; i++) {
     yield arr[i];
   }
@@ -130,14 +118,6 @@ function dropRight<A extends Iterable<unknown> | AsyncIterable<unknown>>(
     throw new RangeError("'length' must be greater than 0");
   }
 
-  if (isArray(iterable)) {
-    return arrayDropRight<A>(length, iterable);
-  }
-
-  if (isString(iterable)) {
-    return stringDropRight(length, iterable) as any;
-  }
-
   if (isIterable<A>(iterable)) {
     return sync(length, iterable);
   }
diff --git a/src/Lazy/reverse.ts b/src/Lazy/reverse.ts
index 24e05139..f76766c1 100644
--- a/src/Lazy/reverse.ts
+++ b/src/Lazy/reverse.ts
@@ -5,21 +5,9 @@ import { isAsyncIterable, isIterable } from "../_internal/utils";
 import ReturnIterableIteratorType from "../types/ReturnIterableIteratorType";
 import concurrent, { isConcurrent } from "./concurrent";
 
-function* stringReverse(str: string) {
-  const arr = Array.from(str);
-  for (let i = arr.length - 1; i >= 0; i--) {
-    yield arr[i];
-  }
-}
-
-function* arrayReverse<T>(arr: Array<T>) {
-  for (let i = arr.length - 1; i >= 0; i--) {
-    yield arr[i];
-  }
-}
-
 function* sync<T>(iterable: Iterable<T>) {
-  const arr = toArray(iterable);
+  const arr =
+    isArray(iterable) || isString(iterable) ? iterable : toArray(iterable);
   for (let i = arr.length - 1; i >= 0; i--) {
     yield arr[i];
   }
@@ -92,14 +80,6 @@ function reverse<T extends Iterable<unknown> | AsyncIterable<unknown>>(
 function reverse<T extends Iterable<unknown> | AsyncIterable<unknown>>(
   iterable: T,
 ) {
-  if (isArray(iterable)) {
-    return arrayReverse(iterable);
-  }
-
-  if (isString(iterable)) {
-    return stringReverse(iterable);
-  }
-
   if (isIterable(iterable)) {
     return sync(iterable);
   }
diff --git a/src/Lazy/takeRight.ts b/src/Lazy/takeRight.ts
index fe21764d..b1387551 100644
--- a/src/Lazy/takeRight.ts
+++ b/src/Lazy/takeRight.ts
@@ -6,23 +6,9 @@ import isArray from "../isArray";
 import isString from "../isString";
 import concurrent, { isConcurrent } from "./concurrent";
 
-function* stringTakeRight(length: number, str: string) {
-  const arr = Array.from(str);
-  const index = arr.length - length;
-  for (let i = index; i < arr.length; i++) {
-    if (arr[i]) yield arr[i];
-  }
-}
-
-function* arrayTakeRight<A>(length: number, arr: Array<A>) {
-  const index = arr.length - length;
-  for (let i = index; i < arr.length; i++) {
-    if (arr[i]) yield arr[i];
-  }
-}
-
 function* sync<A>(length: number, iterable: Iterable<A>): IterableIterator<A> {
-  const arr = toArray(iterable);
+  const arr =
+    isArray(iterable) || isString(iterable) ? iterable : toArray(iterable);
   const index = arr.length - length;
   for (let i = index; i < arr.length; i++) {
     if (arr[i]) yield arr[i];
@@ -129,14 +115,6 @@ function takeRight<A extends Iterable<unknown> | AsyncIterable<unknown>>(
     };
   }
 
-  if (isArray(iterable)) {
-    return arrayTakeRight<A>(l, iterable) as any;
-  }
-
-  if (isString(iterable)) {
-    return stringTakeRight(l, iterable) as any;
-  }
-
   if (isIterable<IterableInfer<A>>(iterable)) {
     return sync(l, iterable);
   }
diff --git a/src/gt.ts b/src/gt.ts
new file mode 100644
index 00000000..851d0479
--- /dev/null
+++ b/src/gt.ts
@@ -0,0 +1,39 @@
+/**
+ * Returns true if the first argument is greater than the second; false otherwise.
+ *
+ * @example
+ * ```ts
+ * gt(5, 1) // expected true
+ * gt(1, 5) // expected false
+ * gt("a", "b") // expected false
+ * gt("b", "a") // expected true
+ *
+ * filter(gt(5), [1, 2, 4, 5, 8, 9]) // Iterable<[1, 2, 4]>
+ * filter(gt(1), [1, 2, 3, 4, 5]) // Iterable<[]>
+ * filter(gt("b"), ["a", "b", "c"]) // Iterable<["a"]>
+ * filter(gt("a"), ["a", "b"]) // Itreable<[]>
+ * ```
+ */
+
+function gt(a: string): (b: string) => boolean;
+function gt(a: number): (b: number) => boolean;
+function gt(a: Date): (b: Date) => boolean;
+function gt(a: string, b: string): boolean;
+function gt(a: number, b: number): boolean;
+function gt(a: Date, b: Date): boolean;
+
+function gt(a: any, b?: any): ((b: any) => boolean) | boolean {
+  if (b === undefined) {
+    return (_b: any) => gt(a, _b);
+  }
+
+  if (a.constructor !== b.constructor) {
+    throw new TypeError(
+      "The values you want to compare must be of the same type",
+    );
+  }
+
+  return a > b;
+}
+
+export default gt;
diff --git a/src/gte.ts b/src/gte.ts
new file mode 100644
index 00000000..fe21c785
--- /dev/null
+++ b/src/gte.ts
@@ -0,0 +1,39 @@
+/**
+ * Returns true if the first argument is greater or equal than the second; false otherwise.
+ *
+ * @example
+ * ```ts
+ * gte(5, 1) // expected true
+ * gte(1, 1) // expected true
+ * gte(1, 5) // expected false
+ * gte("a", "b") // expected false
+ * gte("b", "a") // expected true
+ *
+ * filter(gte(5), [1, 2, 4, 5, 8, 9]) // Iterable<[1, 2, 4, 5]>
+ * filter(gte(1), [2, 3, 4]) // Iterable<[]>
+ * filter(gte("b"), ["a", "b", "c"]) // Iterable<["a", "b"]>
+ * filter(gte("a"), ["b"]) // Itreable<[]>
+ * ```
+ */
+function gte(a: string): (b: string) => boolean;
+function gte(a: number): (b: number) => boolean;
+function gte(a: Date): (b: Date) => boolean;
+function gte(a: string, b: string): boolean;
+function gte(a: number, b: number): boolean;
+function gte(a: Date, b: Date): boolean;
+
+function gte(a: any, b?: any): ((b: any) => boolean) | boolean {
+  if (b === undefined) {
+    return (_b: any) => gte(a, _b);
+  }
+
+  if (a.constructor !== b.constructor) {
+    throw new TypeError(
+      "The values you want to compare must be of the same type",
+    );
+  }
+
+  return a >= b;
+}
+
+export default gte;
diff --git a/src/index.ts b/src/index.ts
index 83ddd560..718c1c61 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -12,6 +12,8 @@ import find from "./find";
 import findIndex from "./findIndex";
 import fromEntries from "./fromEntries";
 import groupBy from "./groupBy";
+import gt from "./gt";
+import gte from "./gte";
 import head from "./head";
 import identity from "./identity";
 import includes from "./includes";
@@ -22,9 +24,12 @@ import isNil from "./isNil";
 import isNumber from "./isNumber";
 import isObject from "./isObject";
 import isString from "./isString";
+import isUndefined from "./isUndefined";
 import join from "./join";
 import juxt from "./juxt";
 import last from "./last";
+import lt from "./lt";
+import lte from "./lte";
 import max from "./max";
 import min from "./min";
 import noop from "./noop";
@@ -45,6 +50,7 @@ import sortBy from "./sortBy";
 import sum from "./sum";
 import tap from "./tap";
 import toArray from "./toArray";
+import unicodeToArray from "./unicodeToArray";
 
 export {
   add,
@@ -62,6 +68,8 @@ export {
   findIndex,
   fromEntries,
   groupBy,
+  gt,
+  gte,
   head,
   head as first,
   identity,
@@ -74,9 +82,12 @@ export {
   isNumber,
   isObject,
   isString,
+  isUndefined,
   join,
   juxt,
   last,
+  lt,
+  lte,
   max,
   min,
   noop,
@@ -97,6 +108,7 @@ export {
   sum,
   tap,
   toArray,
+  unicodeToArray,
 };
 
 export * from "./Lazy/index";
diff --git a/src/isUndefined.ts b/src/isUndefined.ts
new file mode 100644
index 00000000..39dd9056
--- /dev/null
+++ b/src/isUndefined.ts
@@ -0,0 +1,14 @@
+/**
+ * Returns true if `a` is a undefined.
+ *
+ * @example
+ * ```ts
+ * isUndefined(undefined); // true
+ * isUndefined(2); // false
+ * ```
+ */
+function isUndefined(a: any): a is undefined {
+  return typeof a === "undefined";
+}
+
+export default isUndefined;
diff --git a/src/lt.ts b/src/lt.ts
new file mode 100644
index 00000000..c1acaa0a
--- /dev/null
+++ b/src/lt.ts
@@ -0,0 +1,38 @@
+/**
+ * Returns true if the first argument is less than the second; false otherwise.
+ *
+ * @example
+ * ```ts
+ * lt(5, 1) // expected false
+ * lt(1, 5) // expected true
+ * lt("a", "b") // expected true
+ * lt("b", "a") // expected false
+ *
+ * filter(lt(5), [1, 2, 4, 5, 8, 9]) // Iterable<[8, 9]>
+ * filter(lt(7), [5, 6, 7]) // Iterable<[]>
+ * filter(lt("b"), ["a", "b", "c"]) // Iterable<["c"]>
+ * filter(lt("e"), ["b", "c", "d"]) // Itreable<[]>
+ * ```
+ */
+function lt(a: string): (b: string) => boolean;
+function lt(a: number): (b: number) => boolean;
+function lt(a: Date): (b: Date) => boolean;
+function lt(a: string, b: string): boolean;
+function lt(a: number, b: number): boolean;
+function lt(a: Date, b: Date): boolean;
+
+function lt(a: any, b?: any): ((b: any) => boolean) | boolean {
+  if (b === undefined) {
+    return (_b: any) => lt(a, _b);
+  }
+
+  if (a.constructor !== b.constructor) {
+    throw new TypeError(
+      "The values you want to compare must be of the same type",
+    );
+  }
+
+  return a < b;
+}
+
+export default lt;
diff --git a/src/lte.ts b/src/lte.ts
new file mode 100644
index 00000000..a2bcbe10
--- /dev/null
+++ b/src/lte.ts
@@ -0,0 +1,39 @@
+/**
+ * Returns true if the first argument is less or equal than the second; false otherwise.
+ *
+ * @example
+ * ```ts
+ * lte(5, 1) // expected false
+ * lte(1, 1) // expected true
+ * lte(1, 5) // expected true
+ * lte("a", "b") // expected true
+ * lte("b", "a") // expected false
+ *
+ * filter(lte(5), [1, 2, 4, 5, 8, 9]) // Iterable<[5, 8, 9]>
+ * filter(lte(9), [6, 7, 8]) // Iterable<[]>
+ * filter(lte("b"), ["a", "b", "c"]) // Iterable<["b", "c"]>
+ * filter(lte("e"), ["c", "d"]) // Itreable<[]>
+ * ```
+ */
+function lte(a: string): (b: string) => boolean;
+function lte(a: number): (b: number) => boolean;
+function lte(a: Date): (b: Date) => boolean;
+function lte(a: string, b: string): boolean;
+function lte(a: number, b: number): boolean;
+function lte(a: Date, b: Date): boolean;
+
+function lte(a: any, b?: any): ((b: any) => boolean) | boolean {
+  if (b === undefined) {
+    return (_b: any) => lte(a, _b);
+  }
+
+  if (a.constructor !== b.constructor) {
+    throw new TypeError(
+      "The values you want to compare must be of the same type",
+    );
+  }
+
+  return a <= b;
+}
+
+export default lte;
diff --git a/src/unicodeToArray.ts b/src/unicodeToArray.ts
new file mode 100644
index 00000000..8d1c9675
--- /dev/null
+++ b/src/unicodeToArray.ts
@@ -0,0 +1,59 @@
+// source: https://github.com/lodash/lodash/blob/master/.internal/unicodeToArray.js
+
+/** Used to compose unicode character classes. */
+const rsAstralRange = "\\ud800-\\udfff";
+const rsComboMarksRange = "\\u0300-\\u036f";
+const reComboHalfMarksRange = "\\ufe20-\\ufe2f";
+const rsComboSymbolsRange = "\\u20d0-\\u20ff";
+const rsComboMarksExtendedRange = "\\u1ab0-\\u1aff";
+const rsComboMarksSupplementRange = "\\u1dc0-\\u1dff";
+const rsComboRange =
+  rsComboMarksRange +
+  reComboHalfMarksRange +
+  rsComboSymbolsRange +
+  rsComboMarksExtendedRange +
+  rsComboMarksSupplementRange;
+const rsVarRange = "\\ufe0e\\ufe0f";
+
+/** Used to compose unicode capture groups. */
+const rsAstral = `[${rsAstralRange}]`;
+const rsCombo = `[${rsComboRange}]`;
+const rsFitz = "\\ud83c[\\udffb-\\udfff]";
+const rsModifier = `(?:${rsCombo}|${rsFitz})`;
+const rsNonAstral = `[^${rsAstralRange}]`;
+const rsRegional = "(?:\\ud83c[\\udde6-\\uddff]){2}";
+const rsSurrPair = "[\\ud800-\\udbff][\\udc00-\\udfff]";
+const rsZWJ = "\\u200d";
+
+/** Used to compose unicode regexes. */
+const reOptMod = `${rsModifier}?`;
+const rsOptVar = `[${rsVarRange}]?`;
+const rsOptJoin = `(?:${rsZWJ}(?:${[rsNonAstral, rsRegional, rsSurrPair].join(
+  "|",
+)})${rsOptVar + reOptMod})*`;
+const rsSeq = rsOptVar + reOptMod + rsOptJoin;
+const rsNonAstralCombo = `${rsNonAstral}${rsCombo}?`;
+const rsSymbol = `(?:${[
+  rsNonAstralCombo,
+  rsCombo,
+  rsRegional,
+  rsSurrPair,
+  rsAstral,
+].join("|")})`;
+
+/** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */
+const reUnicode = RegExp(`${rsFitz}(?=${rsFitz})|${rsSymbol + rsSeq}`, "g");
+
+/**
+ * Converts a Unicode `string` to an array.
+ *
+ * * @example
+ * * ```ts
+ * *  unicodeToArray('🙇‍♂️🤩😭'); // ['🙇‍♂️','🤩','😭'];
+ * * ```
+ */
+function unicodeToArray(string: string) {
+  return string.match(reUnicode) || [];
+}
+
+export default unicodeToArray;
diff --git a/website/function.json b/website/function.json
index cfaa4550..f417d05f 100644
--- a/website/function.json
+++ b/website/function.json
@@ -68,6 +68,7 @@
     "isNumber",
     "isObject",
     "isString",
+    "isUndefined",
     "join",
     "juxt",
     "last",


Test patch:
diff --git a/test/gt.spec.ts b/test/gt.spec.ts
new file mode 100644
index 00000000..fd2f06e0
--- /dev/null
+++ b/test/gt.spec.ts
@@ -0,0 +1,65 @@
+import { filter, gt, pipe, toArray } from "../src/index";
+
+describe("gt(greater then)", function () {
+  describe("currying", function () {
+    it("given array then should return array with filtered values greater than 5", function () {
+      const result = pipe([4, 5, 6], filter(gt(5)), toArray);
+      expect(result).toEqual([4]);
+    });
+    it("given array then should return empty array", function () {
+      const result = pipe([5, 6, 7], filter(gt(5)), toArray);
+      expect(result).toEqual([]);
+    });
+
+    it("given string array then should return [a, b]", function () {
+      const result = pipe(["a", "b", "c", "d", "e"], filter(gt("c")), toArray);
+      expect(result).toEqual(["a", "b"]);
+    });
+    it("given string array then should return empty array", function () {
+      const result = pipe(["a", "b", "c", "d"], filter(gt("a")), toArray);
+      expect(result).toEqual([]);
+    });
+    it("given date array then should return date array", function () {
+      const result = pipe(
+        [new Date(2022, 4, 10), new Date(2022, 3, 9)],
+        filter(gt(new Date(2022, 3, 10))),
+        toArray,
+      );
+
+      expect(result).toEqual([new Date(2022, 3, 9)]);
+    });
+
+    it("given data array then should return empty array", function () {
+      const result = pipe(
+        [new Date(2021, 4, 10), new Date(2021, 3, 9)],
+        filter(gt(new Date(2020, 9, 12))),
+        toArray,
+      );
+
+      expect(result).toEqual([]);
+    });
+  });
+
+  describe("eager evaluation", function () {
+    it("should return true that the first number is greater than second", function () {
+      expect(gt(5, 1)).toEqual(true);
+    });
+    it("should return false that the first number is not greater than second", function () {
+      expect(gt(1, 5)).toEqual(false);
+    });
+
+    it("should return true that the first char is greater than second", function () {
+      expect(gt("b", "a")).toEqual(true);
+    });
+    it("should return false that the first char is not greater than second", function () {
+      expect(gt("b", "c")).toEqual(false);
+    });
+
+    it("should return true that the first Date is greater than second", function () {
+      expect(gt(new Date(), new Date(2021, 4, 11))).toEqual(true);
+    });
+    it("should return false that the first Date is not greater than second", function () {
+      expect(gt(new Date(2021, 4, 11), new Date())).toEqual(false);
+    });
+  });
+});
diff --git a/test/gte.spec.ts b/test/gte.spec.ts
new file mode 100644
index 00000000..d17fec10
--- /dev/null
+++ b/test/gte.spec.ts
@@ -0,0 +1,74 @@
+import { filter, gte, pipe, toArray } from "../src/index";
+
+describe("gte(greater then or equal to)", function () {
+  describe("currying", function () {
+    it("given array then should return greater values", function () {
+      const result = pipe([4, 5, 6], filter(gte(5)), toArray);
+      expect(result).toEqual([4, 5]);
+    });
+    it("given array then should return empty array", function () {
+      const result = pipe([5, 6, 7], filter(gte(4)), toArray);
+      expect(result).toEqual([]);
+    });
+
+    it("given string array then should return [a, b, c]", function () {
+      const result = pipe(["a", "b", "c", "d", "e"], filter(gte("c")), toArray);
+      expect(result).toEqual(["a", "b", "c"]);
+    });
+    it("given string array then should return empty array", function () {
+      const result = pipe(["b", "c", "d"], filter(gte("a")), toArray);
+      expect(result).toEqual([]);
+    });
+    it("given date array then should return date array", function () {
+      const result = pipe(
+        [new Date(2022, 4, 10), new Date(2022, 3, 9), new Date(2022, 4, 11)],
+        filter(gte(new Date(2022, 4, 10))),
+        toArray,
+      );
+
+      expect(result).toEqual([new Date(2022, 4, 10), new Date(2022, 3, 9)]);
+    });
+
+    it("given data array then should return empty array", function () {
+      const result = pipe(
+        [new Date(2021, 4, 10), new Date(2021, 3, 9)],
+        filter(gte(new Date(2020, 4, 10))),
+        toArray,
+      );
+
+      expect(result).toEqual([]);
+    });
+  });
+
+  describe("eager evaluation", function () {
+    it("should return true that the first number is greater than second", function () {
+      expect(gte(5, 1)).toEqual(true);
+    });
+    it("should return true that the first number is equal to second", function () {
+      expect(gte(5, 5)).toEqual(true);
+    });
+    it("should return false that the first number is not greater than or not equal to second", function () {
+      expect(gte(1, 5)).toEqual(false);
+    });
+
+    it("should return true that the first char is greater than second", function () {
+      expect(gte("b", "a")).toEqual(true);
+    });
+    it("should return true that the first char is equal to second", function () {
+      expect(gte("b", "b")).toEqual(true);
+    });
+
+    it("should return false that the first char is not greater than or not equal to second", function () {
+      expect(gte("b", "c")).toEqual(false);
+    });
+    it("should return true that the first Date is less than second", function () {
+      expect(gte(new Date(), new Date(2021, 4, 11))).toEqual(true);
+    });
+    it("should return true that the first Date is equal to second", function () {
+      expect(gte(new Date(2021, 4, 11), new Date(2021, 4, 11))).toEqual(true);
+    });
+    it("should return false that the first Date is not less than second", function () {
+      expect(gte(new Date(2021, 4, 11), new Date())).toEqual(false);
+    });
+  });
+});
diff --git a/test/isUndefined.spec.ts b/test/isUndefined.spec.ts
new file mode 100644
index 00000000..23b68b4e
--- /dev/null
+++ b/test/isUndefined.spec.ts
@@ -0,0 +1,16 @@
+import isUndefined from "../src/isUndefined";
+
+describe("isUndefined", function () {
+  it.each([2, true, null, {}, [], Symbol("a"), "a"])(
+    "given non undefined then should be false",
+    function (a) {
+      const result = isUndefined(a);
+      expect(result).toEqual(false);
+    },
+  );
+
+  it("given undefined then should be true", function () {
+    const result = isUndefined(undefined);
+    expect(result).toEqual(true);
+  });
+});
diff --git a/test/lt.spec.ts b/test/lt.spec.ts
new file mode 100644
index 00000000..588a37a6
--- /dev/null
+++ b/test/lt.spec.ts
@@ -0,0 +1,63 @@
+import { filter, lt, pipe, toArray } from "../src/index";
+
+describe("lt(less then)", function () {
+  describe("currying", function () {
+    it("given array then should return little values", function () {
+      const result = pipe([4, 5, 6], filter(lt(5)), toArray);
+      expect(result).toEqual([6]);
+    });
+    it("given array then should return empty array", function () {
+      const result = pipe([5, 6, 7], filter(lt(7)), toArray);
+      expect(result).toEqual([]);
+    });
+
+    it("given string array then should return [e]", function () {
+      const result = pipe(["a", "b", "c", "d", "e"], filter(lt("d")), toArray);
+      expect(result).toEqual(["e"]);
+    });
+    it("given string array then should return empty array", function () {
+      const result = pipe(["a", "b", "c", "d"], filter(lt("d")), toArray);
+      expect(result).toEqual([]);
+    });
+    it("given date array then should return date array", function () {
+      const result = pipe(
+        [new Date(2022, 4, 10), new Date(2022, 3, 9)],
+        filter(lt(new Date(2022, 3, 10))),
+        toArray,
+      );
+
+      expect(result).toEqual([new Date(2022, 4, 10)]);
+    });
+
+    it("given data array then should return empty array", function () {
+      const result = pipe(
+        [new Date(2021, 4, 10), new Date(2021, 3, 9)],
+        filter(lt(new Date())),
+        toArray,
+      );
+
+      expect(result).toEqual([]);
+    });
+  });
+  describe("eager evaluation", function () {
+    it("should return true that the first number is less than second", function () {
+      expect(lt(1, 5)).toEqual(true);
+    });
+    it("should return false that the first number is not less than second", function () {
+      expect(lt(5, 1)).toEqual(false);
+    });
+
+    it("should return true that the first char is less than second", function () {
+      expect(lt("a", "b")).toEqual(true);
+    });
+    it("should return false that the first char is not less than second", function () {
+      expect(lt("c", "b")).toEqual(false);
+    });
+    it("should return true that the first Date is less than second", function () {
+      expect(lt(new Date(2021, 4, 11), new Date())).toEqual(true);
+    });
+    it("should return false that the first Date is not less than second", function () {
+      expect(lt(new Date(), new Date(2021, 4, 11))).toEqual(false);
+    });
+  });
+});
diff --git a/test/lte.spec.ts b/test/lte.spec.ts
new file mode 100644
index 00000000..0426ad24
--- /dev/null
+++ b/test/lte.spec.ts
@@ -0,0 +1,75 @@
+import { filter, lte, pipe, toArray } from "../src/index";
+
+describe("lte(less then or equal to)", function () {
+  describe("currying", function () {
+    it("given array then should return little values", function () {
+      const result = pipe([4, 5, 6], filter(lte(5)), toArray);
+      expect(result).toEqual([5, 6]);
+    });
+    it("given array then should return empty array", function () {
+      const result = pipe([6, 7], filter(lte(8)), toArray);
+      expect(result).toEqual([]);
+    });
+
+    it("given string array then should return [d, e]", function () {
+      const result = pipe(["a", "b", "c", "d", "e"], filter(lte("d")), toArray);
+      expect(result).toEqual(["d", "e"]);
+    });
+    it("given string array then should return empty array", function () {
+      const result = pipe(["b", "c", "d"], filter(lte("e")), toArray);
+      expect(result).toEqual([]);
+    });
+    it("given date array then should return date array", function () {
+      const result = pipe(
+        [new Date(2022, 2, 10), new Date(2022, 3, 9), new Date(2022, 3, 10)],
+        filter(lte(new Date(2022, 3, 8))),
+        toArray,
+      );
+
+      expect(result).toEqual([new Date(2022, 3, 9), new Date(2022, 3, 10)]);
+    });
+
+    it("given data array then should return empty array", function () {
+      const result = pipe(
+        [new Date(2021, 4, 10), new Date(2021, 3, 9)],
+        filter(lte(new Date())),
+        toArray,
+      );
+
+      expect(result).toEqual([]);
+    });
+  });
+
+  describe("eager evaluation", function () {
+    it("should return true that the first number is less than second", function () {
+      expect(lte(1, 5)).toEqual(true);
+    });
+    it("should return true that the first number is equal to second", function () {
+      expect(lte(5, 5)).toEqual(true);
+    });
+    it("should return false that the first number is not less than or not equal to second", function () {
+      expect(lte(5, 1)).toEqual(false);
+    });
+
+    it("should return true that the first char is less to second", function () {
+      expect(lte("a", "b")).toEqual(true);
+    });
+    it("should return true that the first char is equal to second", function () {
+      expect(lte("b", "b")).toEqual(true);
+    });
+
+    it("should return false that the first char is not less than or not equal to second", function () {
+      expect(lte("c", "b")).toEqual(false);
+    });
+    it("should return true that the first Date is less than second", function () {
+      expect(lte(new Date(2021, 4, 11), new Date())).toEqual(true);
+    });
+    it("should return true that the first Date is equal to second", function () {
+      expect(lte(new Date(2021, 4, 11), new Date(2021, 4, 11))).toEqual(true);
+    });
+
+    it("should return false that the first Date is not less than second", function () {
+      expect(lte(new Date(), new Date(2021, 4, 11))).toEqual(false);
+    });
+  });
+});
diff --git a/type-check/gt.test.ts b/type-check/gt.test.ts
new file mode 100644
index 00000000..05520a9c
--- /dev/null
+++ b/type-check/gt.test.ts
@@ -0,0 +1,30 @@
+import * as Test from "../src/types/Test";
+import { gt, pipe, filter, toArray, toAsync } from "../src";
+
+const { checks, check } = Test;
+
+const res1 = gt(5);
+const res2 = res1(10);
+
+const res3 = gt("b");
+const res4 = res3("a");
+
+const res5 = gt(new Date());
+const res6 = res5(new Date(2021, 4, 11));
+
+const res7 = pipe(toAsync([1, 2, 3, 4, 5]), filter(gt(3)), toArray);
+
+const res8 = gt(1, 2);
+const res9 = gt("a", "b");
+
+checks([
+  check<typeof res1, (b: number) => boolean, Test.Pass>(),
+  check<typeof res2, boolean, Test.Pass>(),
+  check<typeof res3, (b: string) => boolean, Test.Pass>(),
+  check<typeof res4, boolean, Test.Pass>(),
+  check<typeof res5, (b: Date) => boolean, Test.Pass>(),
+  check<typeof res6, boolean, Test.Pass>(),
+  check<typeof res7, Promise<number[]>, Test.Pass>(),
+  check<typeof res8, boolean, Test.Pass>(),
+  check<typeof res9, boolean, Test.Pass>(),
+]);
diff --git a/type-check/gte.test.ts b/type-check/gte.test.ts
new file mode 100644
index 00000000..b0088a77
--- /dev/null
+++ b/type-check/gte.test.ts
@@ -0,0 +1,30 @@
+import * as Test from "../src/types/Test";
+import { gte, pipe, filter, toArray, toAsync } from "../src";
+
+const { checks, check } = Test;
+
+const res1 = gte(5);
+const res2 = res1(10);
+
+const res3 = gte("b");
+const res4 = res3("a");
+
+const res5 = gte(new Date());
+const res6 = res5(new Date(2021, 4, 11));
+
+const res7 = pipe(toAsync([1, 2, 3, 4, 5]), filter(gte(3)), toArray);
+
+const res8 = gte(1, 2);
+const res9 = gte("a", "b");
+
+checks([
+  check<typeof res1, (b: number) => boolean, Test.Pass>(),
+  check<typeof res2, boolean, Test.Pass>(),
+  check<typeof res3, (b: string) => boolean, Test.Pass>(),
+  check<typeof res4, boolean, Test.Pass>(),
+  check<typeof res5, (b: Date) => boolean, Test.Pass>(),
+  check<typeof res6, boolean, Test.Pass>(),
+  check<typeof res7, Promise<number[]>, Test.Pass>(),
+  check<typeof res8, boolean, Test.Pass>(),
+  check<typeof res9, boolean, Test.Pass>(),
+]);
diff --git a/type-check/isUndefined.test.ts b/type-check/isUndefined.test.ts
new file mode 100644
index 00000000..f6268cbd
--- /dev/null
+++ b/type-check/isUndefined.test.ts
@@ -0,0 +1,14 @@
+import * as Test from "../src/types/Test";
+import { filter, isUndefined, pipe } from "../src";
+
+const { checks, check } = Test;
+
+const res1 = isUndefined(undefined);
+const res2 = isUndefined(3);
+const res3 = pipe([1, undefined, 2], filter(isUndefined));
+
+checks([
+  check<typeof res1, boolean, Test.Pass>(),
+  check<typeof res2, boolean, Test.Pass>(),
+  check<typeof res3, IterableIterator<undefined>, Test.Pass>(),
+]);
diff --git a/type-check/lt.test.ts b/type-check/lt.test.ts
new file mode 100644
index 00000000..b7e4d237
--- /dev/null
+++ b/type-check/lt.test.ts
@@ -0,0 +1,30 @@
+import * as Test from "../src/types/Test";
+import { lt, pipe, filter, toArray, toAsync } from "../src";
+
+const { checks, check } = Test;
+
+const res1 = lt(5);
+const res2 = res1(10);
+
+const res3 = lt("b");
+const res4 = res3("a");
+
+const res5 = lt(new Date());
+const res6 = res5(new Date(2021, 4, 11));
+
+const res7 = pipe(toAsync([1, 2, 3, 4, 5]), filter(lt(3)), toArray);
+
+const res8 = lt(1, 2);
+const res9 = lt("a", "b");
+
+checks([
+  check<typeof res1, (b: number) => boolean, Test.Pass>(),
+  check<typeof res2, boolean, Test.Pass>(),
+  check<typeof res3, (b: string) => boolean, Test.Pass>(),
+  check<typeof res4, boolean, Test.Pass>(),
+  check<typeof res5, (b: Date) => boolean, Test.Pass>(),
+  check<typeof res6, boolean, Test.Pass>(),
+  check<typeof res7, Promise<number[]>, Test.Pass>(),
+  check<typeof res8, boolean, Test.Pass>(),
+  check<typeof res9, boolean, Test.Pass>(),
+]);
diff --git a/type-check/lte.test.ts b/type-check/lte.test.ts
new file mode 100644
index 00000000..30b4d90e
--- /dev/null
+++ b/type-check/lte.test.ts
@@ -0,0 +1,30 @@
+import * as Test from "../src/types/Test";
+import { lte, pipe, filter, toArray, toAsync } from "../src";
+
+const { checks, check } = Test;
+
+const res1 = lte(5);
+const res2 = res1(10);
+
+const res3 = lte("b");
+const res4 = res3("a");
+
+const res5 = lte(new Date());
+const res6 = res5(new Date(2021, 4, 11));
+
+const res7 = pipe(toAsync([1, 2, 3, 4, 5]), filter(lte(3)), toArray);
+
+const res8 = lte(1, 2);
+const res9 = lte("a", "b");
+
+checks([
+  check<typeof res1, (b: number) => boolean, Test.Pass>(),
+  check<typeof res2, boolean, Test.Pass>(),
+  check<typeof res3, (b: string) => boolean, Test.Pass>(),
+  check<typeof res4, boolean, Test.Pass>(),
+  check<typeof res5, (b: Date) => boolean, Test.Pass>(),
+  check<typeof res6, boolean, Test.Pass>(),
+  check<typeof res7, Promise<number[]>, Test.Pass>(),
+  check<typeof res8, boolean, Test.Pass>(),
+  check<typeof res9, boolean, Test.Pass>(),
+]);