Skip to content

Commit 2f800d4

Browse files
authoredMar 28, 2025
Revert "Revert "types: make init hooks types accurately reflect runtime behavior""
1 parent 1a308de commit 2f800d4

File tree

4 files changed

+63
-117
lines changed

4 files changed

+63
-117
lines changed
 

‎test/types/middleware.preposttypes.test.ts

+30-116
Original file line numberDiff line numberDiff line change
@@ -67,47 +67,6 @@ schema.pre('init', function() {
6767
expectType<HydratedDocument<IDocument>>(this);
6868
});
6969

70-
schema.post('init', function(res) {
71-
expectType<HydratedDocument<IDocument>>(this);
72-
expectNotType<Query<any, any>>(res);
73-
});
74-
75-
schema.pre('init', { document: true, query: false }, function() {
76-
expectType<HydratedDocument<IDocument>>(this);
77-
});
78-
79-
schema.post('init', { document: true, query: false }, function(res) {
80-
expectType<HydratedDocument<IDocument>>(this);
81-
expectNotType<Query<any, any>>(res);
82-
});
83-
84-
schema.pre('init', { document: true, query: true }, function() {
85-
expectType<HydratedDocument<IDocument>>(this);
86-
});
87-
88-
schema.post('init', { document: true, query: true }, function(res) {
89-
expectType<HydratedDocument<IDocument>>(this);
90-
expectNotType<Query<any, any>>(res);
91-
});
92-
93-
schema.pre('init', { document: false, query: true }, function() {
94-
expectType<never>(this);
95-
});
96-
97-
schema.post('init', { document: false, query: true }, function(res) {
98-
expectType<never>(this);
99-
expectNotType<Query<any, any>>(res);
100-
});
101-
102-
schema.pre('init', { document: false, query: false }, function() {
103-
expectType<never>(this);
104-
});
105-
106-
schema.post('init', { document: false, query: false }, function(res) {
107-
expectType<never>(this);
108-
expectNotType<Query<any, any>>(res);
109-
});
110-
11170
schema.pre('estimatedDocumentCount', function() {
11271
expectType<Query<any, any>>(this);
11372
});
@@ -693,51 +652,6 @@ schema.post('deleteOne', { document: false, query: false }, function(res) {
693652
expectNotType<Query<any, any>>(res);
694653
});
695654

696-
schema.pre(['save', 'init'], function() {
697-
expectType<HydratedDocument<IDocument>>(this);
698-
});
699-
700-
schema.post(['save', 'init'], function(res) {
701-
expectType<HydratedDocument<IDocument>>(this);
702-
expectNotType<Query<any, any>>(res);
703-
});
704-
705-
schema.pre(['save', 'init'], { document: true, query: false }, function() {
706-
expectType<HydratedDocument<IDocument>>(this);
707-
});
708-
709-
schema.post(['save', 'init'], { document: true, query: false }, function(res) {
710-
expectType<HydratedDocument<IDocument>>(this);
711-
expectNotType<Query<any, any>>(res);
712-
});
713-
714-
schema.pre(['save', 'init'], { document: true, query: true }, function() {
715-
expectType<HydratedDocument<IDocument>>(this);
716-
});
717-
718-
schema.post(['save', 'init'], { document: true, query: true }, function(res) {
719-
expectType<HydratedDocument<IDocument>>(this);
720-
expectNotType<Query<any, any>>(res);
721-
});
722-
723-
schema.pre(['save', 'init'], { document: false, query: true }, function() {
724-
expectType<never>(this);
725-
});
726-
727-
schema.post(['save', 'init'], { document: false, query: true }, function(res) {
728-
expectType<never>(this);
729-
expectNotType<Query<any, any>>(res);
730-
});
731-
732-
schema.pre(['save', 'init'], { document: false, query: false }, function() {
733-
expectType<never>(this);
734-
});
735-
736-
schema.post(['save', 'init'], { document: false, query: false }, function(res) {
737-
expectType<never>(this);
738-
expectNotType<Query<any, any>>(res);
739-
});
740-
741655
schema.pre(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany'], function() {
742656
expectType<Query<any, any>>(this);
743657
});
@@ -828,137 +742,137 @@ schema.post(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct
828742
expectNotType<Query<any, any>>(res);
829743
});
830744

831-
schema.pre(['save', 'init', 'updateOne', 'deleteOne', 'validate'], function() {
745+
schema.pre(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], function() {
832746
expectType<Query<any, any>|HydratedDocument<IDocument>>(this);
833747
});
834748

835-
schema.post(['save', 'init', 'updateOne', 'deleteOne', 'validate'], function(res) {
749+
schema.post(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], function(res) {
836750
expectType<Query<any, any>|HydratedDocument<IDocument>>(this);
837751
expectNotType<Query<any, any>>(res);
838752
});
839753

840-
schema.pre(['save', 'init', 'updateOne', 'deleteOne', 'validate'], { document: false, query: true }, function() {
754+
schema.pre(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], { document: false, query: true }, function() {
841755
expectType<Query<any, any>>(this);
842756
});
843757

844-
schema.post(['save', 'init', 'updateOne', 'deleteOne', 'validate'], { document: false, query: true }, function(res) {
758+
schema.post(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], { document: false, query: true }, function(res) {
845759
expectType<Query<any, any>>(this);
846760
expectNotType<Query<any, any>>(res);
847761
});
848762

849-
schema.pre(['save', 'init', 'updateOne', 'deleteOne', 'validate'], { document: true, query: false }, function() {
763+
schema.pre(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], { document: true, query: false }, function() {
850764
expectType<HydratedDocument<IDocument>>(this);
851765
});
852766

853-
schema.post(['save', 'init', 'updateOne', 'deleteOne', 'validate'], { document: true, query: false }, function(res) {
767+
schema.post(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], { document: true, query: false }, function(res) {
854768
expectType<HydratedDocument<IDocument>>(this);
855769
expectNotType<Query<any, any>>(res);
856770
});
857771

858-
schema.pre(['save', 'init', 'updateOne', 'deleteOne', 'validate'], { document: true, query: true }, function() {
772+
schema.pre(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], { document: true, query: true }, function() {
859773
expectType<Query<any, any>|HydratedDocument<IDocument>>(this);
860774
});
861775

862-
schema.post(['save', 'init', 'updateOne', 'deleteOne', 'validate'], { document: true, query: true }, function(res) {
776+
schema.post(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], { document: true, query: true }, function(res) {
863777
expectType<Query<any, any>|HydratedDocument<IDocument>>(this);
864778
expectNotType<Query<any, any>>(res);
865779
});
866780

867-
schema.pre(['save', 'init', 'updateOne', 'deleteOne', 'validate'], { document: false, query: false }, function() {
781+
schema.pre(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], { document: false, query: false }, function() {
868782
expectType<never>(this);
869783
});
870784

871-
schema.post(['save', 'init', 'updateOne', 'deleteOne', 'validate'], { document: false, query: false }, function(res) {
785+
schema.post(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], { document: false, query: false }, function(res) {
872786
expectType<never>(this);
873787
expectNotType<Query<any, any>>(res);
874788
});
875789

876-
schema.pre(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], function() {
790+
schema.pre(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'updateOne', 'deleteOne', 'validate'], function() {
877791
expectType<Query<any, any>|HydratedDocument<IDocument>>(this);
878792
});
879793

880-
schema.post(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], function(res) {
794+
schema.post(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'updateOne', 'deleteOne', 'validate'], function(res) {
881795
expectType<Query<any, any>|HydratedDocument<IDocument>>(this);
882796
expectNotType<Query<any, any>>(res);
883797
});
884798

885-
schema.pre(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], { document: false, query: true }, function() {
799+
schema.pre(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'updateOne', 'deleteOne', 'validate'], { document: false, query: true }, function() {
886800
expectType<Query<any, any>>(this);
887801
});
888802

889-
schema.post(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], { document: false, query: true }, function(res) {
803+
schema.post(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'updateOne', 'deleteOne', 'validate'], { document: false, query: true }, function(res) {
890804
expectType<Query<any, any>>(this);
891805
expectNotType<Query<any, any>>(res);
892806
});
893807

894-
schema.pre(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], { document: true, query: false }, function() {
808+
schema.pre(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'updateOne', 'deleteOne', 'validate'], { document: true, query: false }, function() {
895809
expectType<HydratedDocument<IDocument>>(this);
896810
});
897811

898-
schema.post(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], { document: true, query: false }, function(res) {
812+
schema.post(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'updateOne', 'deleteOne', 'validate'], { document: true, query: false }, function(res) {
899813
expectType<HydratedDocument<IDocument>>(this);
900814
expectNotType<Query<any, any>>(res);
901815
});
902816

903-
schema.pre(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], { document: true, query: true }, function() {
817+
schema.pre(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'updateOne', 'deleteOne', 'validate'], { document: true, query: true }, function() {
904818
expectType<Query<any, any>|HydratedDocument<IDocument>>(this);
905819
});
906820

907-
schema.post(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], { document: true, query: true }, function(res) {
821+
schema.post(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'updateOne', 'deleteOne', 'validate'], { document: true, query: true }, function(res) {
908822
expectType<Query<any, any>|HydratedDocument<IDocument>>(this);
909823
expectNotType<Query<any, any>>(res);
910824
});
911825

912-
schema.pre(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], { document: false, query: false }, function() {
826+
schema.pre(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'updateOne', 'deleteOne', 'validate'], { document: false, query: false }, function() {
913827
expectType<never>(this);
914828
});
915829

916-
schema.post(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'updateOne', 'deleteOne', 'validate'], { document: false, query: false }, function(res) {
830+
schema.post(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'updateOne', 'deleteOne', 'validate'], { document: false, query: false }, function(res) {
917831
expectType<never>(this);
918832
expectNotType<Query<any, any>>(res);
919833
});
920834

921-
schema.pre(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'init', 'updateOne', 'deleteOne', 'validate'], function() {
835+
schema.pre(['save', 'updateOne', 'deleteOne', 'validate'], function() {
922836
expectType<Query<any, any>|HydratedDocument<IDocument>>(this);
923837
});
924838

925-
schema.post(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'init', 'updateOne', 'deleteOne', 'validate'], function(res) {
839+
schema.post(['save', 'updateOne', 'deleteOne', 'validate'], function(res) {
926840
expectType<Query<any, any>|HydratedDocument<IDocument>>(this);
927841
expectNotType<Query<any, any>>(res);
928842
});
929843

930-
schema.pre(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'init', 'updateOne', 'deleteOne', 'validate'], { document: false, query: true }, function() {
844+
schema.pre(['save', 'updateOne', 'deleteOne', 'validate'], { document: false, query: true }, function() {
931845
expectType<Query<any, any>>(this);
932846
});
933847

934-
schema.post(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'init', 'updateOne', 'deleteOne', 'validate'], { document: false, query: true }, function(res) {
848+
schema.post(['save', 'updateOne', 'deleteOne', 'validate'], { document: false, query: true }, function(res) {
935849
expectType<Query<any, any>>(this);
936850
expectNotType<Query<any, any>>(res);
937851
});
938852

939-
schema.pre(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'init', 'updateOne', 'deleteOne', 'validate'], { document: true, query: false }, function() {
853+
schema.pre(['save', 'updateOne', 'deleteOne', 'validate'], { document: true, query: false }, function() {
940854
expectType<HydratedDocument<IDocument>>(this);
941855
});
942856

943-
schema.post(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'init', 'updateOne', 'deleteOne', 'validate'], { document: true, query: false }, function(res) {
857+
schema.post(['save', 'updateOne', 'deleteOne', 'validate'], { document: true, query: false }, function(res) {
944858
expectType<HydratedDocument<IDocument>>(this);
945859
expectNotType<Query<any, any>>(res);
946860
});
947861

948-
schema.pre(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'init', 'updateOne', 'deleteOne', 'validate'], { document: true, query: true }, function() {
862+
schema.pre(['save', 'updateOne', 'deleteOne', 'validate'], { document: true, query: true }, function() {
949863
expectType<Query<any, any>|HydratedDocument<IDocument>>(this);
950864
});
951865

952-
schema.post(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'init', 'updateOne', 'deleteOne', 'validate'], { document: true, query: true }, function(res) {
866+
schema.post(['save', 'updateOne', 'deleteOne', 'validate'], { document: true, query: true }, function(res) {
953867
expectType<Query<any, any>|HydratedDocument<IDocument>>(this);
954868
expectNotType<Query<any, any>>(res);
955869
});
956870

957-
schema.pre(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'init', 'updateOne', 'deleteOne', 'validate'], { document: false, query: false }, function() {
871+
schema.pre(['save', 'updateOne', 'deleteOne', 'validate'], { document: false, query: false }, function() {
958872
expectType<never>(this);
959873
});
960874

961-
schema.post(['estimatedDocumentCount', 'countDocuments', 'deleteMany', 'distinct', 'find', 'findOne', 'findOneAndDelete', 'findOneAndReplace', 'findOneAndUpdate', 'replaceOne', 'updateMany', 'save', 'init', 'updateOne', 'deleteOne', 'validate'], { document: false, query: false }, function(res) {
875+
schema.post(['save', 'updateOne', 'deleteOne', 'validate'], { document: false, query: false }, function(res) {
962876
expectType<never>(this);
963877
expectNotType<Query<any, any>>(res);
964878
});

‎test/types/schema.test.ts

+31
Original file line numberDiff line numberDiff line change
@@ -1747,6 +1747,37 @@ async function schemaDouble() {
17471747
expectType<Types.Double | null | undefined>(doc.balance);
17481748
}
17491749

1750+
function gh15301() {
1751+
interface IUser {
1752+
time: { hours: number, minutes: number }
1753+
}
1754+
const userSchema = new Schema<IUser>({
1755+
time: {
1756+
type: new Schema(
1757+
{
1758+
hours: { type: Number, required: true },
1759+
minutes: { type: Number, required: true }
1760+
},
1761+
{ _id: false }
1762+
),
1763+
required: true
1764+
}
1765+
});
1766+
1767+
const timeStringToObject = (time) => {
1768+
if (typeof time !== 'string') return time;
1769+
const [hours, minutes] = time.split(':');
1770+
return { hours: parseInt(hours), minutes: parseInt(minutes) };
1771+
};
1772+
1773+
userSchema.pre('init', function(rawDoc) {
1774+
expectType<IUser>(rawDoc);
1775+
if (typeof rawDoc.time === 'string') {
1776+
rawDoc.time = timeStringToObject(rawDoc.time);
1777+
}
1778+
});
1779+
}
1780+
17501781
function defaultReturnsUndefined() {
17511782
const schema = new Schema<{ arr: number[] }>({
17521783
arr: {

0 commit comments

Comments
 (0)
Failed to load comments.