diff --git a/test/types/lean.test.ts b/test/types/lean.test.ts index 745999d3aa0..7886f2b8b7c 100644 --- a/test/types/lean.test.ts +++ b/test/types/lean.test.ts @@ -176,7 +176,7 @@ async function gh13345_2() { const PlaceModel = model('Place', placeSchema); const place = await PlaceModel.findOne().lean().orFail().exec(); - expectAssignable>(place); + expectAssignable(place); expectType>(place.images[0].description); } diff --git a/test/types/models.test.ts b/test/types/models.test.ts index a53404c5c00..51e646e1f44 100644 --- a/test/types/models.test.ts +++ b/test/types/models.test.ts @@ -644,7 +644,7 @@ async function gh13705() { const schema = new Schema({ name: String }); const TestModel = model('Test', schema); - type ExpectedLeanDoc = (mongoose.FlattenMaps<{ name?: string }> & { _id: mongoose.Types.ObjectId }); + type ExpectedLeanDoc = ({ name?: string } & { _id: mongoose.Types.ObjectId }); const findByIdRes = await TestModel.findById('0'.repeat(24), undefined, { lean: true }); expectType(findByIdRes); diff --git a/test/types/schema.test.ts b/test/types/schema.test.ts index 45dd2653c31..180e2de9a1a 100644 --- a/test/types/schema.test.ts +++ b/test/types/schema.test.ts @@ -15,7 +15,8 @@ import { SchemaType, Types, Query, - model + model, + InferHydratedDocumentType } from 'mongoose'; import { expectType, expectError, expectAssignable } from 'tsd'; import { ObtainDocumentPathType, ResolvePathType } from '../../types/inferschematype'; @@ -403,8 +404,8 @@ export function autoTypedSchema() { objectId2?: Types.ObjectId; objectId3?: Types.ObjectId; customSchema?: Int8; - map1?: Map; - map2?: Map; + map1?: Record; + map2?: Record; array1: string[]; array2: any[]; array3: any[]; @@ -1133,6 +1134,11 @@ function maps() { }); const Test = model('Test', schema); + type Test1 = ObtainSchemaGeneric; + expectType>({} as Test1['myMap']); + type THydratedDocumentType = InferHydratedDocumentType; + expectType>({} as THydratedDocumentType['myMap']); + const doc = new Test({ myMap: { answer: 42 } }); expectType>(doc.myMap); expectType(doc.myMap!.get('answer')); diff --git a/types/index.d.ts b/types/index.d.ts index 95653baf5a4..2a53c0e1778 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -79,16 +79,16 @@ declare module 'mongoose' { collection?: string, options?: CompileModelOptions ): Model< - InferSchemaType, - ObtainSchemaGeneric, - ObtainSchemaGeneric, - ObtainSchemaGeneric, - HydratedDocument< - InferSchemaType, - ObtainSchemaGeneric & ObtainSchemaGeneric, - ObtainSchemaGeneric - >, - TSchema + InferSchemaType, + ObtainSchemaGeneric, + ObtainSchemaGeneric, + ObtainSchemaGeneric, + HydratedDocument< + InferSchemaType, + ObtainSchemaGeneric & ObtainSchemaGeneric, + ObtainSchemaGeneric + >, + TSchema > & ObtainSchemaGeneric; export function model(name: string, schema?: Schema | Schema, collection?: string, options?: CompileModelOptions): Model; @@ -230,7 +230,11 @@ declare module 'mongoose' { ObtainDocumentType>, ResolveSchemaOptions >, - THydratedDocumentType = HydratedDocument + THydratedDocumentType = InferHydratedDocumentType< + DocType, + EnforcedDocType, + ResolveSchemaOptions + > //HydratedDocument > extends events.EventEmitter { /** @@ -658,7 +662,7 @@ declare module 'mongoose' { type FlattenProperty = T extends Map ? Record : T extends TreatAsPrimitives ? T : T extends Types.DocumentArray - ? Types.DocumentArray> : FlattenMaps; + ? Types.DocumentArray : T; export type actualPrimitives = string | boolean | number | bigint | symbol | null | undefined; export type TreatAsPrimitives = actualPrimitives | NativeDate | RegExp | symbol | Error | BigInt | Types.ObjectId | Buffer | Function; diff --git a/types/inferschematype.d.ts b/types/inferschematype.d.ts index 75240ed1675..30538ba2e90 100644 --- a/types/inferschematype.d.ts +++ b/types/inferschematype.d.ts @@ -24,13 +24,35 @@ declare module 'mongoose' { * @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". */ - type ObtainDocumentType = DefaultSchemaOptions> = - IsItRecordAndNotAny extends true ? EnforcedDocType : { - [K in keyof (RequiredPaths & - OptionalPaths)]: ObtainDocumentPathType; - }; + type ObtainDocumentType< + DocDefinition, + EnforcedDocType = any, + TSchemaOptions extends Record = DefaultSchemaOptions, + UseHydratedType = false + > = + IsItRecordAndNotAny extends true ? EnforcedDocType : { + [ + K in keyof (RequiredPaths & + OptionalPaths) + ]: ObtainDocumentPathType< + DocDefinition[K], + TSchemaOptions['typeKey'], + UseHydratedType + >; + }; - /** + /** + * @summary Obtains document schema type from Schema instance. + * @param {Schema} TSchema `typeof` a schema instance. + * @example + * const userSchema = new Schema({userName:String}); + * type UserType = InferSchemaType; + * // result + * type UserType = {userName?: string} + */ + export type InferSchemaType = IfAny>; + + /** * @summary Obtains document schema type from Schema instance. * @param {Schema} TSchema `typeof` a schema instance. * @example @@ -39,7 +61,13 @@ declare module 'mongoose' { * // result * type UserType = {userName?: string} */ - export type InferSchemaType = IfAny>; + export type InferHydratedDocumentType< + DocDefinition, + EnforcedDocType = any, + TSchemaOptions extends Record = DefaultSchemaOptions + > = HydratedDocument< + ObtainDocumentType + >; /** * @summary Obtains schema Generic type by using generic alias. @@ -155,10 +183,15 @@ type OptionalPaths = { * @param {PathValueType} PathValueType Document definition path type. * @param {TypeKey} TypeKey A generic refers to document definition. */ -type ObtainDocumentPathType = ResolvePathType< -PathValueType extends PathWithTypePropertyBaseType ? PathValueType[TypeKey] : PathValueType, -PathValueType extends PathWithTypePropertyBaseType ? Omit : {}, -TypeKey +type ObtainDocumentPathType< + PathValueType, + TypeKey extends string = DefaultTypeKey, + UseHydratedType = false +> = ResolvePathType< + PathValueType extends PathWithTypePropertyBaseType ? PathValueType[TypeKey] : PathValueType, + PathValueType extends PathWithTypePropertyBaseType ? Omit : {}, + TypeKey, + UseHydratedType >; /** @@ -174,7 +207,12 @@ type PathEnumOrString['enum']> = T extends R * @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 string = DefaultSchemaOptions['typeKey']> = +type ResolvePathType< + PathValueType, + Options extends SchemaTypeOptions = {}, + TypeKey extends string = DefaultSchemaOptions['typeKey'], + UseHydratedType = false +> = PathValueType extends Schema ? InferSchemaType : PathValueType extends (infer Item)[] ? IfEquals extends true ? Buffer : - PathValueType extends MapConstructor ? Map> : - IfEquals extends true ? Map> : + PathValueType extends MapConstructor ? (UseHydratedType extends true ? Map> : Record>) : + IfEquals extends true ? (UseHydratedType extends true ? Map> : Record>) : PathValueType extends ArrayConstructor ? any[] : PathValueType extends typeof Schema.Types.Mixed ? any: IfEquals extends true ? any: diff --git a/types/query.d.ts b/types/query.d.ts index 3963481a20b..a7689506ead 100644 --- a/types/query.d.ts +++ b/types/query.d.ts @@ -180,7 +180,7 @@ declare module 'mongoose' { type QueryOpThatReturnsDocument = 'find' | 'findOne' | 'findOneAndUpdate' | 'findOneAndReplace' | 'findOneAndDelete'; type GetLeanResultType = QueryOp extends QueryOpThatReturnsDocument - ? (ResultType extends any[] ? Require_id>[] : Require_id>) + ? (ResultType extends any[] ? Require_id[] : Require_id) : ResultType; class Query implements SessionOperation {