diff --git a/test/types/schema.test.ts b/test/types/schema.test.ts index edb4253ad0d..fcbb1e49c7d 100644 --- a/test/types/schema.test.ts +++ b/test/types/schema.test.ts @@ -2,7 +2,6 @@ import { Schema, Document, SchemaDefinition, - SchemaDefinitionProperty, SchemaTypeOptions, Model, Types, @@ -383,11 +382,13 @@ export function autoTypedSchema() { customSchema?: Int8; map1?: Map; map2?: Map; - array1?: string[]; - array2?: any[]; - array3?: any[]; - array4?: any[]; - array5?: any[]; + array1: string[]; + array2: any[]; + array3: any[]; + array4: any[]; + array5: any[]; + array6: string[]; + array7?: string[]; decimal1?: Types.Decimal128; decimal2?: Types.Decimal128; decimal3?: Types.Decimal128; @@ -428,6 +429,8 @@ export function autoTypedSchema() { array3: [Schema.Types.Mixed], array4: [{}], array5: [], + array6: { type: [String] }, + array7: { type: [String], default: undefined }, decimal1: Schema.Types.Decimal128, decimal2: 'Decimal128', decimal3: 'decimal128' diff --git a/types/inferschematype.d.ts b/types/inferschematype.d.ts index 02384fbdb2d..d18b6a5bada 100644 --- a/types/inferschematype.d.ts +++ b/types/inferschematype.d.ts @@ -1,4 +1,4 @@ -import { Schema, Types, InferSchemaType, ObtainDocumentType, SchemaDefinitionProperty, SchemaType, SchemaTypeOptions, TypeKeyBaseType } from 'mongoose'; +import { Schema, InferSchemaType, SchemaType, SchemaTypeOptions, TypeKeyBaseType, Types } from 'mongoose'; declare module 'mongoose' { /** @@ -6,13 +6,13 @@ declare module 'mongoose' { * @description Obtains document schema type from document Definition OR returns enforced schema type if it's provided. * @param {DocDefinition} DocDefinition A generic equals to the type of document definition "provided in as first parameter in Schema constructor". * @param {EnforcedDocType} EnforcedDocType A generic type enforced by user "provided before schema constructor". - * @param {TypeKey} TypeKey A generic of literal string type. + * @param {TypeKey} TypeKey A generic of literal string type."Refers to the property used for path type definition". */ - type ObtainDocumentType = - IsItRecordAndNotAny extends true ? EnforcedDocType : { - [K in keyof (RequiredPaths & - OptionalPaths)]: ObtainDocumentPathType; - }; + type ObtainDocumentType = + IsItRecordAndNotAny extends true ? EnforcedDocType : { + [K in keyof (RequiredPaths & + OptionalPaths)]: ObtainDocumentPathType; + }; /** * @summary Obtains document schema type from Schema instance. @@ -23,7 +23,7 @@ declare module 'mongoose' { * // result * type UserType = {userName?: string} */ - type InferSchemaType = ObtainSchemaGeneric; + type InferSchemaType = ObtainSchemaGeneric ; /** * @summary Obtains schema Generic type by using generic alias. @@ -64,10 +64,18 @@ type IfEquals = (() => G extends U ? 1 : 0) ? Y : N; /** - * @summary Required path base type. - * @description It helps to check whereas if a path is required OR optional. + * @summary Checks if a document path is required or optional. + * @param {P} P Document path. + * @param {TypeKey} TypeKey A generic of literal string type."Refers to the property used for path type definition". */ -type RequiredPathBaseType = { required: true | [true, string | undefined] }; +type IsPathRequired = + P extends { required: true | [true, string | undefined] } | ArrayConstructor | any[] + ? true + : P extends (Record) + ? P extends { default: undefined } + ? false + : true + : false; /** * @summary Path base type defined by using TypeKey @@ -76,31 +84,20 @@ type RequiredPathBaseType = { required: true | [true, string | undefined] }; */ type PathWithTypePropertyBaseType = { [k in TypeKey]: any }; -/** - * @summary - * @description Gets the type of a path defined by using TypeKey or directly specify type - * @param {PathValueType} PathValueType The schema path - * @param {TypeKey} TypeKey A literal string refers to path type property key. - */ -type PathTypeDefinition = PathValueType extends PathWithTypePropertyBaseType ? PathValueType[TypeKey] : PathValueType; - /** * @summary A Utility to obtain schema's required path keys. * @param {T} T A generic refers to document definition. + * @param {TypeKey} TypeKey A generic of literal string type."Refers to the property used for path type definition". * @returns required paths keys of document definition. */ type RequiredPathKeys = { - [K in keyof T]: T[K] extends RequiredPathBaseType ? IfEquals - // Check if the path's type is an array - : PathTypeDefinition extends any[] - // If the path is an array and is defaulted to undefined, then we remove it from the required keys - ? T[K] extends { default: undefined } ? never : K - : never; + [K in keyof T]: IsPathRequired extends true ? IfEquals : never; }[keyof T]; /** * @summary A Utility to obtain schema's required paths. * @param {T} T A generic refers to document definition. + * @param {TypeKey} TypeKey A generic of literal string type."Refers to the property used for path type definition". * @returns a record contains required paths with the corresponding type. */ type RequiredPaths = { @@ -110,20 +107,17 @@ type RequiredPaths = { /** * @summary A Utility to obtain schema's optional path keys. * @param {T} T A generic refers to document definition. + * @param {TypeKey} TypeKey A generic of literal string type."Refers to the property used for path type definition". * @returns optional paths keys of document definition. */ type OptionalPathKeys = { - [K in keyof T]: T[K] extends RequiredPathBaseType ? never - // Check if the path's type is an array - : PathTypeDefinition extends any[] - // If the path is an array and is defaulted to undefined, then we add it to the optional keys - ? T[K] extends { default: undefined } ? K : never - : K; + [K in keyof T]: IsPathRequired extends true ? never : K; }[keyof T]; /** * @summary A Utility to obtain schema's optional paths. * @param {T} T A generic refers to document definition. + * @param {TypeKey} TypeKey A generic of literal string type."Refers to the property used for path type definition". * @returns a record contains optional paths with the corresponding type. */ type OptionalPaths = { @@ -136,11 +130,12 @@ type OptionalPaths = { * @param {PathValueType} PathValueType Document definition path type. * @param {TypeKey} TypeKey A generic refers to document definition. */ -type ObtainDocumentPathType = ResolvePathType< -TypeKey, -PathTypeDefinition, -PathValueType extends PathWithTypePropertyBaseType ? Omit : {} ->; +type ObtainDocumentPathType = PathValueType extends Schema + ? InferSchemaType + : ResolvePathType< + PathValueType extends PathWithTypePropertyBaseType ? PathValueType[TypeKey] : PathValueType, + PathValueType extends PathWithTypePropertyBaseType ? Omit : {} + >; /** * @param {T} T A generic refers to string path enums. @@ -154,18 +149,21 @@ type PathEnumOrString['enum']> = T extends ( * @param {Options} Options Document definition path options except path type. * @returns Number, "Number" or "number" will be resolved to string type. */ -type ResolvePathType = {}> = - PathValueType extends Schema ? InferSchemaType : - PathValueType extends (infer Item)[] ? IfEquals>[] : - PathValueType extends { [K: string]: SchemaDefinitionProperty } ? ObtainDocumentType : - PathValueType extends StringConstructor | 'string' | 'String' | typeof Schema.Types.String ? PathEnumOrString : - PathValueType extends NumberConstructor | 'number' | 'Number' | typeof Schema.Types.Number ? number : - PathValueType extends DateConstructor | 'date' | 'Date' | typeof Schema.Types.Date ? Date : - PathValueType extends typeof Buffer | 'buffer' | 'Buffer' | typeof Schema.Types.Buffer ? Buffer : - PathValueType extends BooleanConstructor | 'boolean' | 'Boolean' | typeof Schema.Types.Boolean ? boolean : - PathValueType extends 'objectId' | 'ObjectId' | typeof Schema.Types.ObjectId ? Types.ObjectId : - PathValueType extends 'decimal128' | 'Decimal128' | typeof Schema.Types.Decimal128 ? Types.Decimal128 : - PathValueType extends MapConstructor ? Map> : - PathValueType extends ArrayConstructor ? any[] : - PathValueType extends typeof SchemaType ? PathValueType['prototype'] : - any; +type ResolvePathType = {}> = + PathValueType extends Schema ? InferSchemaType : + PathValueType extends (infer Item)[] ? IfEquals>[] : + PathValueType extends StringConstructor | 'string' | 'String' | typeof Schema.Types.String ? PathEnumOrString : + PathValueType extends NumberConstructor | 'number' | 'Number' | typeof Schema.Types.Number ? number : + PathValueType extends DateConstructor | 'date' | 'Date' | typeof Schema.Types.Date ? Date : + PathValueType extends typeof Buffer | 'buffer' | 'Buffer' | typeof Schema.Types.Buffer ? Buffer : + PathValueType extends BooleanConstructor | 'boolean' | 'Boolean' | typeof Schema.Types.Boolean ? boolean : + PathValueType extends 'objectId' | 'ObjectId' | typeof Schema.Types.ObjectId ? Types.ObjectId : + PathValueType extends 'decimal128' | 'Decimal128' | typeof Schema.Types.Decimal128 ? Types.Decimal128 : + PathValueType extends MapConstructor ? Map> : + PathValueType extends ArrayConstructor ? any[] : + PathValueType extends typeof Schema.Types.Mixed ? any: + IfEquals extends true ? any: + IfEquals extends true ? any: + PathValueType extends typeof SchemaType ? PathValueType['prototype'] : + PathValueType extends {} ? PathValueType : + unknown;