Repository: marpple/FxTS
Pull request #207 (2023-05-27 21:58:32)

refactor: remove any type in isUndefined.
- fix(#206): remove any type
- feat: add isDefined function
- feat: add throwIf function


industriously: > Thank you for your contribution
> 
> I have a few questions and requests.
> 
> * How do you usually use the `throwIf` function?
> * Could you please add a type test as well?
>   
>   * https://github.com/marpple/FxTS/tree/main/type-check

I am a backend developer. In backend environments, when possible, I write function logic using `pipe`. In the following cases, I use throwIf:

- If data is retrieved from the database but it is not found, I throw a NotFound error.
- If the return type of an internal utility function represents a failure case, I throw an appropriate error for it.
I take inspiration from Rust's Result<T, E> enum and design my code so that internal functions return failure cases instead of directly throwing errors.


```typescript
export namespace Service {
  export const getOne = <T, R>(input: {
    user_id: string;
    findFirst: (id: string) => Promise<T | null>;
    exception_for_notfound: unknown;
    validator: (input: T) => T;
    mapper: (arg: T) => R;
  }) =>
    pipe(
      input.user_id,

      input.findFirst,

      throwIfNull(() => input.exception_for_notfound), // throwIfNull is throwIf(isNull)

      input.validator,

      input.mapper
    );
}

```

Patch:
diff --git a/src/index.ts b/src/index.ts
index 94b7c57c..353561be 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -24,6 +24,7 @@ import isArray from "./isArray";
 import isBoolean from "./isBoolean";
 import isEmpty from "./isEmpty";
 import isNil from "./isNil";
+import isNull from "./isNull";
 import isNumber from "./isNumber";
 import isObject from "./isObject";
 import isString from "./isString";
@@ -92,6 +93,7 @@ export {
   isObject,
   isString,
   isUndefined,
+  isNull,
   join,
   juxt,
   last,
diff --git a/src/isEmpty.ts b/src/isEmpty.ts
index 4ebe169b..6cc9d016 100644
--- a/src/isEmpty.ts
+++ b/src/isEmpty.ts
@@ -1,62 +1,39 @@
+import isArray from "./isArray";
+import isNil from "./isNil";
+
 /**
  * Returns true if the given value is empty value, false otherwise.
  *
  * @example
  * ```ts
- * isEmpty(1); // false
- * isEmpty(0); // false
- * isEmpty(false); // false
- * isEmpty(true); // false
- * isEmpty(new Date()); // false
- * isEmpty(undefined); // true
- * isEmpty(null); // true
- *
- * isEmpty({}); // true
- * isEmpty({a:1}); // false
- *
- * isEmpty([]); // true
- * isEmpty([1]); // false
- *
- * isEmpty(""); // true
- * isEmpty("a"); // false
+ * isEmpty({}) // true
+ * isEmpty([]) // true
+ * isEmpty(null) // true
+ * isEmpty(undefined) // true
+ * isEmpty("") // true
  *
- * isEmpty(function(){}); // false
- * isEmpty(Symbol("")); // false
+ * isEmpty(0) // false
+ * isEmpty(false) // false
+ * isEmpty(function(){}) // false
+ * isEmpty(Symbol("")) // false
+ * isEmpty(new Date()) // false
  * ```
  */
-function isEmpty(value: unknown): boolean {
-  if (typeof value === "number" || typeof value === "boolean") {
-    return false;
-  }
-
-  if (typeof value === "undefined" || value === null) {
-    return true;
-  }
-
-  if (value instanceof Date) {
-    return false;
-  }
-
-  if (typeof value === "function") {
-    return false;
-  }
+export const isEmpty = (value: unknown): boolean => {
+  if (isNil(value)) return true; // if value is null or undefined.
 
-  if (value instanceof Object && !Object.keys(value).length) {
-    return true;
-  }
+  if (
+    typeof value === "object" &&
+    (value as object)["constructor"] === Object &&
+    Object.getOwnPropertyNames(value).length === 0
+  )
+    return true; // if value is a literal object and have no property or method.
 
-  if (Array.isArray(value)) {
-    if (value.length === 0) {
-      return true;
-    }
-    return false;
-  }
+  if (isArray(value) && value.length === 0) return true; // if value have no item.
 
-  if (value === "") {
-    return true;
-  }
+  if (value === "") return true;
 
   return false;
-}
+};
 
 export default isEmpty;
diff --git a/src/isNil.ts b/src/isNil.ts
index d4f3c70c..def62c93 100644
--- a/src/isNil.ts
+++ b/src/isNil.ts
@@ -1,3 +1,6 @@
+import isNull from "./isNull";
+import isUndefined from "./isUndefined";
+
 type Nullable<T> = T extends null | undefined ? T : never;
 
 /**
@@ -11,12 +14,6 @@ type Nullable<T> = T extends null | undefined ? T : never;
  * isNil(null); // true
  * ```
  */
-function isNil<T>(a: T): a is Nullable<T> {
-  if (a === undefined || a === null) {
-    return true;
-  }
-
-  return false;
-}
+const isNil = <T>(a: T): a is Nullable<T> => isUndefined(a) || isNull(a);
 
 export default isNil;
diff --git a/src/isNull.ts b/src/isNull.ts
new file mode 100644
index 00000000..f38ce1b4
--- /dev/null
+++ b/src/isNull.ts
@@ -0,0 +1,14 @@
+/**
+ * Checks if the given value is `null`.
+ *
+ * @example
+ * ```ts
+ * isNull(1); // false
+ * isNull('1'); // false
+ * isNull(undefined); // false
+ * isNull(null); // true
+ * ```
+ */
+const isNull = <T>(input: T | null): input is null => input === null;
+
+export default isNull;
diff --git a/src/isUndefined.ts b/src/isUndefined.ts
index 39dd9056..42d255b0 100644
--- a/src/isUndefined.ts
+++ b/src/isUndefined.ts
@@ -1,5 +1,5 @@
 /**
- * Returns true if `a` is a undefined.
+ * Checks if the given value is `undefined`.
  *
  * @example
  * ```ts
@@ -7,8 +7,6 @@
  * isUndefined(2); // false
  * ```
  */
-function isUndefined(a: any): a is undefined {
-  return typeof a === "undefined";
-}
+const isUndefined = <T>(a: T | undefined): a is undefined => a === undefined;
 
 export default isUndefined;


Test patch:
diff --git a/test/apply.spec.ts b/test/apply.spec.ts
index f5f62ab2..224e830c 100644
--- a/test/apply.spec.ts
+++ b/test/apply.spec.ts
@@ -1,4 +1,4 @@
-import { apply, pipe, range, toArray } from "../src/index";
+import { apply, pipe, range, toArray } from "../src";
 
 describe("apply", function () {
   it("should apply given list to the function", function () {
diff --git a/test/consume.spec.ts b/test/consume.spec.ts
index fee64ba0..76e2c6ea 100644
--- a/test/consume.spec.ts
+++ b/test/consume.spec.ts
@@ -1,4 +1,4 @@
-import { consume, peek, pipe, toAsync } from "../src/index";
+import { consume, peek, pipe, toAsync } from "../src";
 
 describe("consume", function () {
   describe("sync", function () {
diff --git a/test/countBy.spec.ts b/test/countBy.spec.ts
index 5016eb42..beb6278e 100644
--- a/test/countBy.spec.ts
+++ b/test/countBy.spec.ts
@@ -1,5 +1,5 @@
+import { countBy, filter, pipe, toAsync } from "../src";
 import { AsyncFunctionException } from "../src/_internal/error";
-import { countBy, filter, pipe, toAsync } from "../src/index";
 
 type Obj = {
   category: "clothes" | "pants" | "shoes";
diff --git a/test/each.spec.ts b/test/each.spec.ts
index 47bcd10a..37e75e1a 100644
--- a/test/each.spec.ts
+++ b/test/each.spec.ts
@@ -1,4 +1,4 @@
-import { each, map, pipe, range, toAsync } from "../src/index";
+import { each, map, pipe, range, toAsync } from "../src";
 
 describe("each", function () {
   describe("sync", function () {
diff --git a/test/every.spec.ts b/test/every.spec.ts
index a7c68f35..a8b1d590 100644
--- a/test/every.spec.ts
+++ b/test/every.spec.ts
@@ -1,5 +1,5 @@
+import { every, filter, map, pipe, toAsync } from "../src";
 import { AsyncFunctionException } from "../src/_internal/error";
-import { every, filter, map, pipe, toAsync } from "../src/index";
 
 describe("every", function () {
   describe("sync", function () {
diff --git a/test/evolve.spec.ts b/test/evolve.spec.ts
index 6b3c40e0..31567d9d 100644
--- a/test/evolve.spec.ts
+++ b/test/evolve.spec.ts
@@ -1,4 +1,4 @@
-import { evolve, pipe } from "../src/index";
+import { evolve, pipe } from "../src";
 
 describe("evolve", function () {
   const add1 = (a: number) => a + 1;
diff --git a/test/find.spec.ts b/test/find.spec.ts
index 9381f887..f70ff03c 100644
--- a/test/find.spec.ts
+++ b/test/find.spec.ts
@@ -1,5 +1,5 @@
+import { filter, find, map, pipe, toAsync } from "../src";
 import { AsyncFunctionException } from "../src/_internal/error";
-import { filter, find, map, pipe, toAsync } from "../src/index";
 import type Arrow from "../src/types/Arrow";
 
 describe("find", function () {
diff --git a/test/findIndex.spec.ts b/test/findIndex.spec.ts
index 2e989dd0..e11a0e98 100644
--- a/test/findIndex.spec.ts
+++ b/test/findIndex.spec.ts
@@ -1,5 +1,5 @@
+import { filter, findIndex, map, pipe, toAsync } from "../src";
 import { AsyncFunctionException } from "../src/_internal/error";
-import { filter, findIndex, map, pipe, toAsync } from "../src/index";
 import type Arrow from "../src/types/Arrow";
 
 describe("findIndex", function () {
diff --git a/test/fromEntries.spec.ts b/test/fromEntries.spec.ts
index 2a169d49..de819758 100644
--- a/test/fromEntries.spec.ts
+++ b/test/fromEntries.spec.ts
@@ -1,4 +1,4 @@
-import { fromEntries, toAsync } from "../src/index";
+import { fromEntries, toAsync } from "../src";
 
 //an object from string keyed-value pairs.
 describe("fromEntries", function () {
diff --git a/test/groupBy.spec.ts b/test/groupBy.spec.ts
index 236ffd77..39ba5d53 100644
--- a/test/groupBy.spec.ts
+++ b/test/groupBy.spec.ts
@@ -1,5 +1,5 @@
+import { filter, groupBy, pipe, toAsync } from "../src";
 import { AsyncFunctionException } from "../src/_internal/error";
-import { filter, groupBy, pipe, toAsync } from "../src/index";
 
 type Obj = {
   category: "clothes" | "pants" | "shoes";
diff --git a/test/gt.spec.ts b/test/gt.spec.ts
index fd2f06e0..ee11d5a6 100644
--- a/test/gt.spec.ts
+++ b/test/gt.spec.ts
@@ -1,4 +1,4 @@
-import { filter, gt, pipe, toArray } from "../src/index";
+import { filter, gt, pipe, toArray } from "../src";
 
 describe("gt(greater then)", function () {
   describe("currying", function () {
diff --git a/test/gte.spec.ts b/test/gte.spec.ts
index d17fec10..b7775469 100644
--- a/test/gte.spec.ts
+++ b/test/gte.spec.ts
@@ -1,4 +1,4 @@
-import { filter, gte, pipe, toArray } from "../src/index";
+import { filter, gte, pipe, toArray } from "../src";
 
 describe("gte(greater then or equal to)", function () {
   describe("currying", function () {
diff --git a/test/head.spec.ts b/test/head.spec.ts
index cc61eec5..8be4627d 100644
--- a/test/head.spec.ts
+++ b/test/head.spec.ts
@@ -1,5 +1,5 @@
+import { filter, head, map, pipe, toAsync } from "../src";
 import { range } from "../src/Lazy";
-import { filter, head, map, pipe, toAsync } from "../src/index";
 
 describe("head", function () {
   describe("sync", function () {
diff --git a/test/includes.spec.ts b/test/includes.spec.ts
index 171cf942..e4054825 100644
--- a/test/includes.spec.ts
+++ b/test/includes.spec.ts
@@ -1,4 +1,4 @@
-import { filter, includes, map, pipe, toAsync } from "../src/index";
+import { filter, includes, map, pipe, toAsync } from "../src";
 
 describe("includes", function () {
   describe("sync", function () {
diff --git a/test/indexBy.spec.ts b/test/indexBy.spec.ts
index 481c5475..b9cca15c 100644
--- a/test/indexBy.spec.ts
+++ b/test/indexBy.spec.ts
@@ -1,5 +1,5 @@
+import { filter, indexBy, pipe, toAsync } from "../src";
 import { AsyncFunctionException } from "../src/_internal/error";
-import { filter, indexBy, pipe, toAsync } from "../src/index";
 
 type Obj = {
   category: "clothes" | "pants" | "shoes";
diff --git a/test/isArray.spec.ts b/test/isArray.spec.ts
index f7c4ea63..d2d1dae5 100644
--- a/test/isArray.spec.ts
+++ b/test/isArray.spec.ts
@@ -1,4 +1,4 @@
-import { isArray } from "../src/index";
+import { isArray } from "../src";
 
 describe("isArray", function () {
   it.each([undefined, null, true, 1, "a", Symbol("a"), () => null])(
diff --git a/test/isBoolean.spec.ts b/test/isBoolean.spec.ts
index af210e4c..986ac71b 100644
--- a/test/isBoolean.spec.ts
+++ b/test/isBoolean.spec.ts
@@ -1,4 +1,4 @@
-import { isBoolean } from "../src/index";
+import { isBoolean } from "../src";
 
 describe("isBoolean", function () {
   it.each([undefined, null, 1, "1", Symbol("a"), () => null])(
diff --git a/test/isEmpty.spec.ts b/test/isEmpty.spec.ts
index 613e1120..4cb2ad09 100644
--- a/test/isEmpty.spec.ts
+++ b/test/isEmpty.spec.ts
@@ -1,4 +1,4 @@
-import isEmpty from "../src/isEmpty";
+import { isEmpty } from "../src";
 
 describe("isEmpty", function () {
   const testParameters = [
@@ -22,8 +22,6 @@ describe("isEmpty", function () {
 
   it.each(testParameters)(
     "should Return `true` if the given value is empty value(%s)",
-    function (input, expected) {
-      expect(isEmpty(input)).toEqual(expected);
-    },
+    (input, expected) => expect(isEmpty(input)).toEqual(expected),
   );
 });
diff --git a/test/isNil.spec.ts b/test/isNil.spec.ts
index 2117afbc..a0e90363 100644
--- a/test/isNil.spec.ts
+++ b/test/isNil.spec.ts
@@ -1,4 +1,4 @@
-import { isNil } from "../src/index";
+import { isNil } from "../src";
 
 describe("isNil", function () {
   it("should check if given value is `null` or `undefined`", function () {
diff --git a/test/isNull.spec.ts b/test/isNull.spec.ts
new file mode 100644
index 00000000..4f89d9b3
--- /dev/null
+++ b/test/isNull.spec.ts
@@ -0,0 +1,16 @@
+import { isNull } from "../src";
+
+describe("isNull", function () {
+  it.each([2, true, undefined, {}, [], Symbol("a"), "a"])(
+    "given non null then should be false",
+    function (a) {
+      const result = isNull(a);
+      expect(result).toEqual(false);
+    },
+  );
+
+  it("given null then should be true", function () {
+    const result = isNull(null);
+    expect(result).toEqual(true);
+  });
+});
diff --git a/test/isNumber.spec.ts b/test/isNumber.spec.ts
index 706d114f..e7c21a41 100644
--- a/test/isNumber.spec.ts
+++ b/test/isNumber.spec.ts
@@ -1,4 +1,4 @@
-import { isNumber } from "../src/index";
+import { isNumber } from "../src";
 
 describe("isNumber", function () {
   it.each([undefined, null, true, "1", Symbol("a"), () => null])(
diff --git a/test/isString.spec.ts b/test/isString.spec.ts
index 3575b9d7..9c4cd01a 100644
--- a/test/isString.spec.ts
+++ b/test/isString.spec.ts
@@ -1,4 +1,4 @@
-import { isString } from "../src/index";
+import { isString } from "../src";
 
 describe("isString", function () {
   it.each([undefined, null, true, 1, Symbol("a"), () => null])(
diff --git a/test/isUndefined.spec.ts b/test/isUndefined.spec.ts
index 23b68b4e..b3d513e9 100644
--- a/test/isUndefined.spec.ts
+++ b/test/isUndefined.spec.ts
@@ -1,4 +1,4 @@
-import isUndefined from "../src/isUndefined";
+import { isUndefined } from "../src";
 
 describe("isUndefined", function () {
   it.each([2, true, null, {}, [], Symbol("a"), "a"])(
diff --git a/test/join.spec.ts b/test/join.spec.ts
index 45d32b50..58b3d2ab 100644
--- a/test/join.spec.ts
+++ b/test/join.spec.ts
@@ -1,5 +1,5 @@
+import { filter, join, map, pipe, toAsync } from "../src";
 import { asyncEmpty, empty } from "../src/_internal/utils";
-import { filter, join, map, pipe, toAsync } from "../src/index";
 
 describe("join", function () {
   describe("sync", function () {
diff --git a/test/last.spec.ts b/test/last.spec.ts
index bee13261..6765fa3f 100644
--- a/test/last.spec.ts
+++ b/test/last.spec.ts
@@ -1,4 +1,4 @@
-import { filter, last, map, pipe, range, toAsync } from "../src/index";
+import { filter, last, map, pipe, range, toAsync } from "../src";
 
 describe("last", function () {
   describe("sync", function () {
diff --git a/test/lt.spec.ts b/test/lt.spec.ts
index 588a37a6..5cf6ebb3 100644
--- a/test/lt.spec.ts
+++ b/test/lt.spec.ts
@@ -1,4 +1,4 @@
-import { filter, lt, pipe, toArray } from "../src/index";
+import { filter, lt, pipe, toArray } from "../src";
 
 describe("lt(less then)", function () {
   describe("currying", function () {
diff --git a/test/lte.spec.ts b/test/lte.spec.ts
index 0426ad24..c546dd9b 100644
--- a/test/lte.spec.ts
+++ b/test/lte.spec.ts
@@ -1,4 +1,4 @@
-import { filter, lte, pipe, toArray } from "../src/index";
+import { filter, lte, pipe, toArray } from "../src";
 
 describe("lte(less then or equal to)", function () {
   describe("currying", function () {
diff --git a/test/noop.spec.ts b/test/noop.spec.ts
index f293be99..fa1e5eea 100644
--- a/test/noop.spec.ts
+++ b/test/noop.spec.ts
@@ -1,4 +1,4 @@
-import { noop } from "../src/index";
+import { noop } from "../src";
 
 describe("noop", function () {
   it("should return `undefined`", function () {
diff --git a/test/nth.spec.ts b/test/nth.spec.ts
index 1556d740..2e10d62f 100644
--- a/test/nth.spec.ts
+++ b/test/nth.spec.ts
@@ -1,4 +1,4 @@
-import { filter, map, nth, pipe, toAsync } from "../src/index";
+import { filter, map, nth, pipe, toAsync } from "../src";
 
 describe("nth", function () {
   describe("sync", function () {
diff --git a/test/omit.spec.ts b/test/omit.spec.ts
index c019401f..c06e3b88 100644
--- a/test/omit.spec.ts
+++ b/test/omit.spec.ts
@@ -1,4 +1,4 @@
-import { omit, pipe, toAsync } from "../src/index";
+import { omit, pipe, toAsync } from "../src";
 
 describe("omit", function () {
   describe("sync", function () {
diff --git a/test/omitBy.spec.ts b/test/omitBy.spec.ts
index cdfaeb9b..23bf1d66 100644
--- a/test/omitBy.spec.ts
+++ b/test/omitBy.spec.ts
@@ -1,4 +1,4 @@
-import { omitBy, pipe } from "../src/index";
+import { omitBy, pipe } from "../src";
 
 describe("omitBy", function () {
   describe("sync", function () {
diff --git a/test/partition.spec.ts b/test/partition.spec.ts
index f903cacb..ef63a6be 100644
--- a/test/partition.spec.ts
+++ b/test/partition.spec.ts
@@ -1,5 +1,5 @@
+import { map, partition, pipe, toAsync } from "../src";
 import { AsyncFunctionException } from "../src/_internal/error";
-import { map, partition, pipe, toAsync } from "../src/index";
 
 describe("partition", function () {
   describe("sync", function () {
diff --git a/test/pick.spec.ts b/test/pick.spec.ts
index 64e7cdb0..11f9c618 100644
--- a/test/pick.spec.ts
+++ b/test/pick.spec.ts
@@ -1,4 +1,4 @@
-import { pick, pipe, toAsync } from "../src/index";
+import { pick, pipe, toAsync } from "../src";
 
 describe("pick", function () {
   describe("sync", function () {
diff --git a/test/pickBy.spec.ts b/test/pickBy.spec.ts
index 9097de6a..2ce7b2c3 100644
--- a/test/pickBy.spec.ts
+++ b/test/pickBy.spec.ts
@@ -1,4 +1,4 @@
-import { pickBy, pipe } from "../src/index";
+import { pickBy, pipe } from "../src";
 
 describe("pickBy", function () {
   describe("sync", function () {
diff --git a/test/pipe.spec.ts b/test/pipe.spec.ts
index 24631a87..814de429 100644
--- a/test/pipe.spec.ts
+++ b/test/pipe.spec.ts
@@ -8,7 +8,7 @@ import {
   reduce,
   toArray,
   toAsync,
-} from "../src/index";
+} from "../src";
 
 describe("pipe", function () {
   describe("sync", function () {
diff --git a/test/pipe1.spec.ts b/test/pipe1.spec.ts
index 4e30c513..491df91a 100644
--- a/test/pipe1.spec.ts
+++ b/test/pipe1.spec.ts
@@ -1,4 +1,4 @@
-import { pipe1 } from "../src/index";
+import { pipe1 } from "../src";
 
 const add10 = (a: number) => a + 10;
 const add10Async = async (a: number) => a + 10;
diff --git a/test/prop.spec.ts b/test/prop.spec.ts
index 14ea2ba2..36a5b9ff 100644
--- a/test/prop.spec.ts
+++ b/test/prop.spec.ts
@@ -1,4 +1,4 @@
-import { pipe, prop } from "../src/index";
+import { pipe, prop } from "../src";
 
 describe("prop", () => {
   it("should return the value for the given object property", () => {
diff --git a/test/props.spec.ts b/test/props.spec.ts
index 215da491..82acf427 100644
--- a/test/props.spec.ts
+++ b/test/props.spec.ts
@@ -1,4 +1,4 @@
-import { pipe, props, toArray } from "../src/index";
+import { pipe, props, toArray } from "../src";
 
 describe("props", () => {
   const obj = { a: "v1", b: "v2", c: "v3", d: "v4", e: "v5", f: "v6" };
diff --git a/test/reduce.spec.ts b/test/reduce.spec.ts
index 6710eb83..3f0d4b97 100644
--- a/test/reduce.spec.ts
+++ b/test/reduce.spec.ts
@@ -1,4 +1,4 @@
-import { filter, map, pipe, range, reduce, toAsync } from "../src/index";
+import { filter, map, pipe, range, reduce, toAsync } from "../src";
 
 const addNumber = (a: number, b: number) => a + b;
 const addNumberAsync = async (a: number, b: number) => a + b;
diff --git a/test/some.spec.ts b/test/some.spec.ts
index a24aec3f..df3f4aff 100644
--- a/test/some.spec.ts
+++ b/test/some.spec.ts
@@ -1,5 +1,5 @@
+import { filter, map, pipe, some, toAsync } from "../src";
 import { AsyncFunctionException } from "../src/_internal/error";
-import { filter, map, pipe, some, toAsync } from "../src/index";
 
 describe("some", function () {
   describe("sync", function () {
diff --git a/test/sort.spec.ts b/test/sort.spec.ts
index e8654422..2ec790e2 100644
--- a/test/sort.spec.ts
+++ b/test/sort.spec.ts
@@ -1,4 +1,4 @@
-import { filter, pipe, sort, toAsync } from "../src/index";
+import { filter, pipe, sort, toAsync } from "../src";
 
 describe("sort", function () {
   const sortFn = (a: number | string, b: number | string) => {
diff --git a/test/sortBy.spec.ts b/test/sortBy.spec.ts
index c3034781..5599997e 100644
--- a/test/sortBy.spec.ts
+++ b/test/sortBy.spec.ts
@@ -1,4 +1,4 @@
-import { filter, identity, pipe, sortBy, toAsync } from "../src/index";
+import { filter, identity, pipe, sortBy, toAsync } from "../src";
 
 describe("sortBy", function () {
   describe("sync", function () {
diff --git a/test/tap.spec.ts b/test/tap.spec.ts
index 20bda077..f453c462 100644
--- a/test/tap.spec.ts
+++ b/test/tap.spec.ts
@@ -1,4 +1,4 @@
-import { delay, map, pipe, range, tap, toArray, toAsync } from "../src/index";
+import { delay, map, pipe, range, tap, toArray, toAsync } from "../src";
 import { callFuncAfterTime } from "./utils";
 
 describe("tap", function () {
diff --git a/test/toArray.spec.ts b/test/toArray.spec.ts
index 451e40be..c59ee9cb 100644
--- a/test/toArray.spec.ts
+++ b/test/toArray.spec.ts
@@ -1,4 +1,4 @@
-import { range, toArray, toAsync } from "../src/index";
+import { range, toArray, toAsync } from "../src";
 
 const identityP = <T>(a: T) => Promise.resolve(a);
 
diff --git a/type-check/isNull.test.ts b/type-check/isNull.test.ts
new file mode 100644
index 00000000..7e2e5e6c
--- /dev/null
+++ b/type-check/isNull.test.ts
@@ -0,0 +1,16 @@
+import { filter, isNull, pipe } from "../src";
+import * as Test from "../src/types/Test";
+
+const { checks, check } = Test;
+
+const res1 = isNull(undefined);
+const res2 = isNull(null);
+const res3 = isNull(3);
+const res4 = pipe([1, null, 2], filter(isNull));
+
+checks([
+  check<typeof res1, boolean, Test.Pass>(),
+  check<typeof res2, boolean, Test.Pass>(),
+  check<typeof res3, boolean, Test.Pass>(),
+  check<typeof res4, IterableIterator<null>, Test.Pass>(),
+]);