From 64d4397e007e91ba6f450c4312500605bcb036bf Mon Sep 17 00:00:00 2001
From: mohammad0-0ahmad <kurtular.vadisi@gmail.com>
Date: Tue, 5 Apr 2022 00:52:15 +0200
Subject: [PATCH] Refactor the previous PR.

---
 test/types/schema.test.ts  | 11 ++++++-----
 types/inferschematype.d.ts | 16 ++++++++++++----
 2 files changed, 18 insertions(+), 9 deletions(-)

diff --git a/test/types/schema.test.ts b/test/types/schema.test.ts
index 8fa078e02a7..8eeca8e5939 100644
--- a/test/types/schema.test.ts
+++ b/test/types/schema.test.ts
@@ -1,6 +1,5 @@
 import { Schema, Document, SchemaDefinition, Model, Types, InferSchemaType, SchemaType, Query, HydratedDocument } from 'mongoose';
 import { expectType, expectError, expectAssignable } from 'tsd';
-import { IsTAny } from '../../types/inferschematype';
 
 enum Genre {
   Action,
@@ -364,6 +363,7 @@ export function autoTypedSchema() {
     array2?: Schema.Types.Mixed[];
     array3?: Schema.Types.Mixed[];
     array4?: Schema.Types.Mixed[];
+    array5?: Schema.Types.Mixed[];
   };
 
   const TestSchema = new Schema({
@@ -396,10 +396,11 @@ export function autoTypedSchema() {
     customSchema: Int8,
     map1: { type: Map, of: String },
     map2: { type: Map, of: Number },
-    array1: { type: [String] },
-    array2: { type: Array },
-    array3: { type: [Schema.Types.Mixed] },
-    array4: { type: [{}] }
+    array1: [String],
+    array2: Array,
+    array3: [Schema.Types.Mixed],
+    array4: [{}],
+    array5: []
   });
 
   type InferredTestSchemaType = InferSchemaType<typeof TestSchema>;
diff --git a/types/inferschematype.d.ts b/types/inferschematype.d.ts
index bce112efc3b..e24715a5254 100644
--- a/types/inferschematype.d.ts
+++ b/types/inferschematype.d.ts
@@ -51,9 +51,18 @@ declare module 'mongoose' {
  * @param {T} T A generic type to be checked.
  * @returns true if {@link T} is Record OR false if {@link T} is of any type.
  */
-type IsItRecordAndNotAny<T> = IsTAny<T> extends true ? false : T extends Record<any, any> ? true : false;
+type IsItRecordAndNotAny<T> = IfEquals<T, any, false, T extends Record<any, any> ? true : false>;
 
-type IsTAny<T> = keyof any extends keyof T ? (unknown extends T ? true : false) : false;
+/**
+ * @summary Checks if two types are identical.
+ * @param {T} T The first type to be compared with {@link U}.
+ * @param {U} U The seconde type to be compared with {@link T}.
+ * @param {Y} Y A type to be returned if {@link T} &  {@link U} are identical.
+ * @param {N} N A type to be returned if {@link T} &  {@link U} are not identical.
+ */
+type IfEquals<T, U, Y = true, N = false> =
+    (<G>() => G extends T ? 1 : 0) extends
+    (<G>() => G extends U ? 1 : 0) ? Y : N;
 
 /**
  * @summary Required path base type.
@@ -130,8 +139,7 @@ type PathEnumOrString<T extends SchemaTypeOptions<string>['enum']> = T extends (
  * @returns Number, "Number" or "number" will be resolved to string type.
  */
 type ResolvePathType<PathValueType, Options extends SchemaTypeOptions<PathValueType> = {}> =
-  IsTAny<PathValueType> extends true ? Schema.Types.Mixed:
-    PathValueType extends (infer Item)[] ? ResolvePathType<Item>[] :
+    PathValueType extends (infer Item)[] ? IfEquals<Item, never, Schema.Types.Mixed, ResolvePathType<Item>>[] :
       PathValueType extends StringConstructor | 'string' | 'String' | typeof Schema.Types.String ? PathEnumOrString<Options['enum']> :
         PathValueType extends NumberConstructor | 'number' | 'Number' | typeof Schema.Types.Number ? number :
           PathValueType extends DateConstructor | 'date' | 'Date' | typeof Schema.Types.Date ? Date :