Skip to content

Commit 845ff14

Browse files
committed
types: correctly handle union types in BufferToBinary and related helpers
Fix Automattic#15057
1 parent 4cafc80 commit 845ff14

File tree

2 files changed

+86
-49
lines changed

2 files changed

+86
-49
lines changed

test/types/lean.test.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,3 +206,34 @@ async function gh13382() {
206206
const res = await Test.updateOne({}, { name: 'bar' }).lean();
207207
expectAssignable<{ matchedCount: number, modifiedCount: number }>(res);
208208
}
209+
210+
async function gh15057() {
211+
type Attachment =
212+
| {
213+
type: 'foo';
214+
value?: undefined;
215+
}
216+
| {
217+
type: 'string';
218+
value?: string;
219+
};
220+
221+
const TestSchema = new Schema<Attachment>({
222+
type: { type: String, required: true },
223+
value: { type: String }
224+
});
225+
226+
const AttachmentModel = model<Attachment>('test', TestSchema);
227+
228+
const main = async() => {
229+
const item = await AttachmentModel.findOne().lean();
230+
231+
if (!item) return;
232+
233+
doSomeThing(item);
234+
};
235+
236+
const doSomeThing = (item: Attachment) => {
237+
console.log(item);
238+
};
239+
}

types/index.d.ts

Lines changed: 55 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -712,76 +712,82 @@ declare module 'mongoose' {
712712
/**
713713
* Converts any Buffer properties into mongodb.Binary instances, which is what `lean()` returns
714714
*/
715-
export type BufferToBinary<T> = T extends TreatAsPrimitives ? T : T extends Record<string, any> ? {
716-
[K in keyof T]: T[K] extends Buffer
717-
? mongodb.Binary
718-
: T[K] extends (Buffer | null | undefined)
719-
? mongodb.Binary | null | undefined
720-
: T[K] extends Types.DocumentArray<infer ItemType>
715+
export type BufferToBinary<T> = T extends Buffer
716+
? mongodb.Binary
717+
: T extends TreatAsPrimitives
718+
? T
719+
: T extends Record<string, any> ? {
720+
[K in keyof T]: T[K] extends Buffer
721+
? mongodb.Binary
722+
: T[K] extends Types.DocumentArray<infer ItemType>
721723
? Types.DocumentArray<BufferToBinary<ItemType>>
722724
: T[K] extends Types.Subdocument<unknown, unknown, infer SubdocType>
723725
? HydratedSingleSubdocument<SubdocType>
724726
: BufferToBinary<T[K]>;
725-
} : T;
727+
} : T;
726728

727729
/**
728730
* Converts any Buffer properties into { type: 'buffer', data: [1, 2, 3] } format for JSON serialization
729731
*/
730-
export type BufferToJSON<T> = T extends TreatAsPrimitives ? T : T extends Record<string, any> ? {
731-
[K in keyof T]: T[K] extends Buffer
732-
? { type: 'buffer', data: number[] }
733-
: T[K] extends (Buffer | null | undefined)
734-
? { type: 'buffer', data: number[] } | null | undefined
735-
: T[K] extends Types.DocumentArray<infer ItemType>
736-
? Types.DocumentArray<BufferToBinary<ItemType>>
737-
: T[K] extends Types.Subdocument<unknown, unknown, infer SubdocType>
738-
? HydratedSingleSubdocument<SubdocType>
739-
: BufferToBinary<T[K]>;
740-
} : T;
732+
export type BufferToJSON<T> = T extends Buffer
733+
? { type: 'buffer', data: number[] }
734+
: T extends TreatAsPrimitives
735+
? T
736+
: T extends Record<string, any> ? {
737+
[K in keyof T]: T[K] extends Buffer
738+
? { type: 'buffer', data: number[] }
739+
: T[K] extends Types.DocumentArray<infer ItemType>
740+
? Types.DocumentArray<BufferToBinary<ItemType>>
741+
: T[K] extends Types.Subdocument<unknown, unknown, infer SubdocType>
742+
? HydratedSingleSubdocument<SubdocType>
743+
: BufferToBinary<T[K]>;
744+
} : T;
741745

742746
/**
743747
* Converts any ObjectId properties into strings for JSON serialization
744748
*/
745-
export type ObjectIdToString<T> = T extends TreatAsPrimitives ? T : T extends Record<string, any> ? {
746-
[K in keyof T]: T[K] extends mongodb.ObjectId
747-
? string
748-
: T[K] extends (mongodb.ObjectId | null | undefined)
749-
? string | null | undefined
750-
: T[K] extends Types.DocumentArray<infer ItemType>
751-
? Types.DocumentArray<ObjectIdToString<ItemType>>
752-
: T[K] extends Types.Subdocument<unknown, unknown, infer SubdocType>
753-
? HydratedSingleSubdocument<ObjectIdToString<SubdocType>>
754-
: ObjectIdToString<T[K]>;
755-
} : T;
749+
export type ObjectIdToString<T> = T extends mongodb.ObjectId
750+
? string
751+
: T extends TreatAsPrimitives
752+
? T
753+
: T extends Record<string, any> ? {
754+
[K in keyof T]: T[K] extends mongodb.ObjectId
755+
? string
756+
: T[K] extends Types.DocumentArray<infer ItemType>
757+
? Types.DocumentArray<ObjectIdToString<ItemType>>
758+
: T[K] extends Types.Subdocument<unknown, unknown, infer SubdocType>
759+
? HydratedSingleSubdocument<ObjectIdToString<SubdocType>>
760+
: ObjectIdToString<T[K]>;
761+
} : T;
756762

757763
/**
758764
* Converts any Date properties into strings for JSON serialization
759765
*/
760-
export type DateToString<T> = T extends TreatAsPrimitives ? T : T extends Record<string, any> ? {
761-
[K in keyof T]: T[K] extends NativeDate
762-
? string
763-
: T[K] extends (NativeDate | null | undefined)
764-
? string | null | undefined
765-
: T[K] extends Types.DocumentArray<infer ItemType>
766-
? Types.DocumentArray<DateToString<ItemType>>
767-
: T[K] extends Types.Subdocument<unknown, unknown, infer SubdocType>
768-
? HydratedSingleSubdocument<DateToString<SubdocType>>
769-
: DateToString<T[K]>;
770-
} : T;
766+
export type DateToString<T> = T extends NativeDate
767+
? string
768+
: T extends TreatAsPrimitives
769+
? T
770+
: T extends Record<string, any> ? {
771+
[K in keyof T]: T[K] extends NativeDate
772+
? string
773+
: T[K] extends (NativeDate | null | undefined)
774+
? string | null | undefined
775+
: T[K] extends Types.DocumentArray<infer ItemType>
776+
? Types.DocumentArray<DateToString<ItemType>>
777+
: T[K] extends Types.Subdocument<unknown, unknown, infer SubdocType>
778+
? HydratedSingleSubdocument<DateToString<SubdocType>>
779+
: DateToString<T[K]>;
780+
} : T;
771781

772782
/**
773783
* Converts any Mongoose subdocuments (single nested or doc arrays) into POJO equivalents
774784
*/
775785
export type SubdocsToPOJOs<T> = T extends TreatAsPrimitives ? T : T extends Record<string, any> ? {
776-
[K in keyof T]: T[K] extends NativeDate
777-
? string
778-
: T[K] extends (NativeDate | null | undefined)
779-
? string | null | undefined
780-
: T[K] extends Types.DocumentArray<infer ItemType>
781-
? ItemType[]
782-
: T[K] extends Types.Subdocument<unknown, unknown, infer SubdocType>
783-
? SubdocType
784-
: SubdocsToPOJOs<T[K]>;
786+
[K in keyof T]: T[K] extends Types.DocumentArray<infer ItemType>
787+
? ItemType[]
788+
: T[K] extends Types.Subdocument<unknown, unknown, infer SubdocType>
789+
? SubdocType
790+
: SubdocsToPOJOs<T[K]>;
785791
} : T;
786792

787793
export type JSONSerialized<T> = SubdocsToPOJOs<

0 commit comments

Comments
 (0)