diff --git a/test/types/schema.test.ts b/test/types/schema.test.ts index 1a74fccf027..822c7a20075 100644 --- a/test/types/schema.test.ts +++ b/test/types/schema.test.ts @@ -10,7 +10,9 @@ import { Query, HydratedDocument, SchemaOptions, - ObtainSchemaGeneric + ObtainSchemaGeneric, + DefaultSchemaOptions, + FlatRecord } from 'mongoose'; import { expectType, expectError, expectAssignable } from 'tsd'; @@ -692,14 +694,10 @@ function gh12030() { function gh12122() { const Test1 = new Schema({ test: String }, { typeKey: 'customTypeKey' }); - expectType<{ + expectType & { typeKey: 'customTypeKey'; - id: true; - }>({} as ObtainSchemaGeneric); + }>>({} as ObtainSchemaGeneric); const Test2 = new Schema({ test: String }, {}); - expectType<{ - typeKey: 'type'; - id: true; - }>({} as ObtainSchemaGeneric); + expectType({} as ObtainSchemaGeneric); } diff --git a/types/inferschematype.d.ts b/types/inferschematype.d.ts index 6462e3de160..cb4a1f66d4e 100644 --- a/types/inferschematype.d.ts +++ b/types/inferschematype.d.ts @@ -3,16 +3,16 @@ import { InferSchemaType, SchemaType, SchemaTypeOptions, - TypeKeyBaseType, Types, NumberSchemaDefinition, StringSchemaDefinition, BooleanSchemaDefinition, DateSchemaDefinition, ObtainDocumentType, - DefaultTypeKey, ObjectIdSchemaDefinition, - IfEquals + IfEquals, + SchemaOptions, + DefaultSchemaOptions } from 'mongoose'; declare module 'mongoose' { @@ -21,7 +21,7 @@ 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."Refers to the property used for path type definition". + * @param {TSchemaOptions} TSchemaOptions A generic represent the type of schema options. */ type ObtainDocumentType = DefaultSchemaOptions> = IsItRecordAndNotAny extends true ? EnforcedDocType : { @@ -59,6 +59,10 @@ declare module 'mongoose' { }[alias] : unknown; + /** + * @summary Helper to obtain and resolve the schema options which are has an effect on schema type. + * @param {T} T Schema option to be resolved. + */ type ResolveSchemaOptions = Omit, 'statics' | 'methods' | 'query' | 'virtuals'>; } @@ -68,7 +72,7 @@ declare module 'mongoose' { * @param {P} P Document path. * @param {TypeKey} TypeKey A generic of literal string type."Refers to the property used for path type definition". */ -type IsPathRequired = +type IsPathRequired = P extends { required: true | [true, string | undefined] } | ArrayConstructor | any[] ? true : P extends (Record) @@ -86,7 +90,7 @@ type IsPathRequired = * @description It helps to check if a path is defined by TypeKey OR not. * @param {TypeKey} TypeKey A literal string refers to path type property key. */ -type PathWithTypePropertyBaseType = { [k in TypeKey]: any }; +type PathWithTypePropertyBaseType = { [k in TypeKey]: any }; /** * @summary A Utility to obtain schema's required path keys. @@ -94,7 +98,7 @@ type PathWithTypePropertyBaseType = { [k in Typ * @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 = { +type RequiredPathKeys = { [K in keyof T]: IsPathRequired extends true ? IfEquals : never; }[keyof T]; @@ -104,7 +108,7 @@ type RequiredPathKeys = { * @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 = { +type RequiredPaths = { [K in RequiredPathKeys]: T[K]; }; @@ -114,7 +118,7 @@ type RequiredPaths = { * @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 = { +type OptionalPathKeys = { [K in keyof T]: IsPathRequired extends true ? never : K; }[keyof T]; @@ -124,7 +128,7 @@ type OptionalPathKeys = { * @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 = { +type OptionalPaths = { [K in OptionalPathKeys]?: T[K]; }; @@ -134,7 +138,7 @@ type OptionalPaths = { * @param {PathValueType} PathValueType Document definition path type. * @param {TypeKey} TypeKey A generic refers to document definition. */ -type ObtainDocumentPathType = PathValueType extends Schema +type ObtainDocumentPathType = PathValueType extends Schema ? InferSchemaType : ResolvePathType< PathValueType extends PathWithTypePropertyBaseType ? PathValueType[TypeKey] : PathValueType, @@ -155,7 +159,7 @@ type PathEnumOrString['enum']> = T extends ( * @param {TypeKey} TypeKey A generic of literal string type."Refers to the property used for path type definition". * @returns Number, "Number" or "number" will be resolved to number type. */ -type ResolvePathType = {}, TypeKey extends TypeKeyBaseType = DefaultTypeKey> = +type ResolvePathType = {}, TypeKey extends SchemaOptions['typeKey'] = DefaultSchemaOptions['typeKey']> = PathValueType extends Schema ? InferSchemaType : PathValueType extends (infer Item)[] ? IfEquals> : ResolvePathType[]> : PathValueType extends StringSchemaDefinition ? PathEnumOrString : diff --git a/types/schemaoptions.d.ts b/types/schemaoptions.d.ts index 5fc9b64997b..931f0ff15e2 100644 --- a/types/schemaoptions.d.ts +++ b/types/schemaoptions.d.ts @@ -7,9 +7,6 @@ declare module 'mongoose' { currentTime?: () => (NativeDate | number); } - type TypeKeyBaseType = string; - - type DefaultTypeKey = 'type'; interface SchemaOptions { /** * By default, Mongoose's init() function creates all the indexes defined in your model's schema by @@ -139,7 +136,7 @@ declare module 'mongoose' { * type declaration. However, for applications like geoJSON, the 'type' property is important. If you want to * control which key mongoose uses to find type declarations, set the 'typeKey' schema option. */ - typeKey?: TypeKeyBaseType; + typeKey?: string; /** * By default, documents are automatically validated before they are saved to the database. This is to @@ -186,22 +183,22 @@ declare module 'mongoose' { * You can suppress the warning by setting { supressReservedKeysWarning: true } schema options. Keep in mind that this * can break plugins that rely on these reserved names. */ - supressReservedKeysWarning?: boolean, + supressReservedKeysWarning?: boolean; /** * Model Statics methods. */ - statics?: Record, ...args: any) => unknown> | TStaticMethods, + statics?: Record, ...args: any) => unknown> | TStaticMethods; /** * Document instance methods. */ - methods?: Record, ...args: any) => unknown> | TInstanceMethods, + methods?: Record, ...args: any) => unknown> | TInstanceMethods; /** * Query helper functions. */ - query?: Record>(this: T, ...args: any) => T> | QueryHelpers, + query?: Record>(this: T, ...args: any) => T> | QueryHelpers; /** * Set whether to cast non-array values to arrays. @@ -212,11 +209,14 @@ declare module 'mongoose' { /** * Virtual paths. */ - virtuals?: SchemaOptionsVirtualsPropertyType, + virtuals?: SchemaOptionsVirtualsPropertyType; } interface DefaultSchemaOptions { - typeKey: 'type' - id: true + typeKey: 'type'; + id: true; + _id: '_id'; + timestamps: false; + versionKey: '__v' } }