Skip to content

Commit bbca321

Browse files
authored
Merge pull request #15123 from Automattic/vkarpov15/gh-15122
types: make BufferToBinary avoid Document instances
2 parents 8acb95b + 333b7e7 commit bbca321

File tree

2 files changed

+147
-49
lines changed

2 files changed

+147
-49
lines changed

test/types/lean.test.ts

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Schema, model, Types, InferSchemaType, FlattenMaps } from 'mongoose';
1+
import { Schema, model, Types, InferSchemaType, FlattenMaps, HydratedDocument, Model, Document, PopulatedDoc } from 'mongoose';
22
import { expectAssignable, expectError, expectType } from 'tsd';
33

44
function gh10345() {
@@ -237,3 +237,89 @@ async function gh15057() {
237237
console.log(item);
238238
};
239239
}
240+
241+
async function gh15122() {
242+
interface IChild {
243+
_id: Types.ObjectId;
244+
name: string;
245+
}
246+
247+
type ChildDocumentOverrides = {};
248+
249+
interface IChildVirtuals {
250+
id: string;
251+
}
252+
253+
type ChildInstance = HydratedDocument<
254+
IChild,
255+
ChildDocumentOverrides & IChildVirtuals
256+
>;
257+
258+
type ChildModelType = Model<
259+
IChild,
260+
{},
261+
ChildDocumentOverrides,
262+
IChildVirtuals,
263+
ChildInstance
264+
>;
265+
266+
267+
interface IParent {
268+
_id: Types.ObjectId;
269+
name: string;
270+
surname: string;
271+
child: PopulatedDoc<Document<Types.ObjectId> & IChild>;
272+
}
273+
274+
type ParentDocumentOverrides = {};
275+
276+
interface IParentVirtuals {
277+
id: string;
278+
fullName: string;
279+
}
280+
281+
type ParentInstance = HydratedDocument<
282+
IParent,
283+
ParentDocumentOverrides & IParentVirtuals
284+
>;
285+
286+
type ParentModelType = Model<
287+
IParent,
288+
{},
289+
ParentDocumentOverrides,
290+
IParentVirtuals,
291+
ParentInstance
292+
>;
293+
294+
const parentSchema = new Schema<IParent, ParentModelType>(
295+
{
296+
name: {
297+
type: String,
298+
required: true,
299+
trim: true
300+
},
301+
surname: {
302+
type: String,
303+
required: true,
304+
trim: true
305+
},
306+
child: {
307+
type: 'ObjectId',
308+
ref: 'Child',
309+
required: true
310+
}
311+
}
312+
);
313+
314+
parentSchema.virtual('fullName').get(function() {
315+
return `${this.name} ${this.surname}`;
316+
});
317+
318+
const Parent = model<IParent, ParentModelType>('Parent', parentSchema);
319+
320+
const testFn = (parent: IParent) => {};
321+
const parentDoc = await Parent.findOne().lean();
322+
if (parentDoc) {
323+
testFn(parentDoc);
324+
}
325+
}

types/index.d.ts

Lines changed: 60 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -715,81 +715,93 @@ declare module 'mongoose' {
715715
*/
716716
export type BufferToBinary<T> = T extends Buffer
717717
? mongodb.Binary
718-
: T extends TreatAsPrimitives
718+
: T extends Document
719719
? T
720-
: T extends Record<string, any> ? {
721-
[K in keyof T]: T[K] extends Buffer
722-
? mongodb.Binary
723-
: T[K] extends Types.DocumentArray<infer ItemType>
724-
? Types.DocumentArray<BufferToBinary<ItemType>>
725-
: T[K] extends Types.Subdocument<unknown, unknown, infer SubdocType>
726-
? HydratedSingleSubdocument<SubdocType>
727-
: BufferToBinary<T[K]>;
720+
: T extends TreatAsPrimitives
721+
? T
722+
: T extends Record<string, any> ? {
723+
[K in keyof T]: T[K] extends Buffer
724+
? mongodb.Binary
725+
: T[K] extends Types.DocumentArray<infer ItemType>
726+
? Types.DocumentArray<BufferToBinary<ItemType>>
727+
: T[K] extends Types.Subdocument<unknown, unknown, infer SubdocType>
728+
? HydratedSingleSubdocument<BufferToBinary<SubdocType>>
729+
: BufferToBinary<T[K]>;
728730
} : T;
729731

730732
/**
731733
* Converts any Buffer properties into { type: 'buffer', data: [1, 2, 3] } format for JSON serialization
732734
*/
733735
export type BufferToJSON<T> = T extends Buffer
734736
? { type: 'buffer', data: number[] }
735-
: T extends TreatAsPrimitives
737+
: T extends Document
736738
? T
737-
: T extends Record<string, any> ? {
738-
[K in keyof T]: T[K] extends Buffer
739-
? { type: 'buffer', data: number[] }
740-
: T[K] extends Types.DocumentArray<infer ItemType>
741-
? Types.DocumentArray<BufferToBinary<ItemType>>
742-
: T[K] extends Types.Subdocument<unknown, unknown, infer SubdocType>
743-
? HydratedSingleSubdocument<SubdocType>
744-
: BufferToBinary<T[K]>;
745-
} : T;
739+
: T extends TreatAsPrimitives
740+
? T
741+
: T extends Record<string, any> ? {
742+
[K in keyof T]: T[K] extends Buffer
743+
? { type: 'buffer', data: number[] }
744+
: T[K] extends Types.DocumentArray<infer ItemType>
745+
? Types.DocumentArray<BufferToBinary<ItemType>>
746+
: T[K] extends Types.Subdocument<unknown, unknown, infer SubdocType>
747+
? HydratedSingleSubdocument<SubdocType>
748+
: BufferToBinary<T[K]>;
749+
} : T;
746750

747751
/**
748752
* Converts any ObjectId properties into strings for JSON serialization
749753
*/
750754
export type ObjectIdToString<T> = T extends mongodb.ObjectId
751755
? string
752-
: T extends TreatAsPrimitives
756+
: T extends Document
753757
? T
754-
: T extends Record<string, any> ? {
755-
[K in keyof T]: T[K] extends mongodb.ObjectId
756-
? string
757-
: T[K] extends Types.DocumentArray<infer ItemType>
758-
? Types.DocumentArray<ObjectIdToString<ItemType>>
759-
: T[K] extends Types.Subdocument<unknown, unknown, infer SubdocType>
760-
? HydratedSingleSubdocument<ObjectIdToString<SubdocType>>
761-
: ObjectIdToString<T[K]>;
762-
} : T;
758+
: T extends TreatAsPrimitives
759+
? T
760+
: T extends Record<string, any> ? {
761+
[K in keyof T]: T[K] extends mongodb.ObjectId
762+
? string
763+
: T[K] extends Types.DocumentArray<infer ItemType>
764+
? Types.DocumentArray<ObjectIdToString<ItemType>>
765+
: T[K] extends Types.Subdocument<unknown, unknown, infer SubdocType>
766+
? HydratedSingleSubdocument<ObjectIdToString<SubdocType>>
767+
: ObjectIdToString<T[K]>;
768+
} : T;
763769

764770
/**
765771
* Converts any Date properties into strings for JSON serialization
766772
*/
767773
export type DateToString<T> = T extends NativeDate
768774
? string
769-
: T extends TreatAsPrimitives
775+
: T extends Document
770776
? T
771-
: T extends Record<string, any> ? {
772-
[K in keyof T]: T[K] extends NativeDate
773-
? string
774-
: T[K] extends (NativeDate | null | undefined)
775-
? string | null | undefined
776-
: T[K] extends Types.DocumentArray<infer ItemType>
777-
? Types.DocumentArray<DateToString<ItemType>>
778-
: T[K] extends Types.Subdocument<unknown, unknown, infer SubdocType>
779-
? HydratedSingleSubdocument<DateToString<SubdocType>>
780-
: DateToString<T[K]>;
781-
} : T;
777+
: T extends TreatAsPrimitives
778+
? T
779+
: T extends Record<string, any> ? {
780+
[K in keyof T]: T[K] extends NativeDate
781+
? string
782+
: T[K] extends (NativeDate | null | undefined)
783+
? string | null | undefined
784+
: T[K] extends Types.DocumentArray<infer ItemType>
785+
? Types.DocumentArray<DateToString<ItemType>>
786+
: T[K] extends Types.Subdocument<unknown, unknown, infer SubdocType>
787+
? HydratedSingleSubdocument<DateToString<SubdocType>>
788+
: DateToString<T[K]>;
789+
} : T;
782790

783791
/**
784792
* Converts any Mongoose subdocuments (single nested or doc arrays) into POJO equivalents
785793
*/
786-
export type SubdocsToPOJOs<T> = T extends TreatAsPrimitives ? T : T extends Record<string, any> ? {
787-
[K in keyof T]: T[K] extends Types.DocumentArray<infer ItemType>
788-
? ItemType[]
789-
: T[K] extends Types.Subdocument<unknown, unknown, infer SubdocType>
790-
? SubdocType
791-
: SubdocsToPOJOs<T[K]>;
792-
} : T;
794+
export type SubdocsToPOJOs<T> = T extends Document
795+
? T
796+
: T extends TreatAsPrimitives
797+
? T
798+
: T extends Record<string, any> ? {
799+
[K in keyof T]: T[K] extends Types.DocumentArray<infer ItemType>
800+
? ItemType[]
801+
: T[K] extends Types.Subdocument<unknown, unknown, infer SubdocType>
802+
? SubdocType
803+
: SubdocsToPOJOs<T[K]>;
804+
} : T;
793805

794806
export type JSONSerialized<T> = SubdocsToPOJOs<
795807
FlattenMaps<

0 commit comments

Comments
 (0)