Skip to content

Commit

Permalink
Add separate RootFilterQuery to type some cases better, add test cases
Browse files Browse the repository at this point in the history
  • Loading branch information
alex-statsig committed Aug 3, 2024
1 parent 330dd36 commit ea2a4ef
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 58 deletions.
27 changes: 27 additions & 0 deletions test/types/models.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ function find() {
Project.find({ name: 'Hello' });

// just callback
// @ts-expect-error: Callback to find is longer supported
Project.find((error: CallbackError, result: IProject[]) => console.log(error, result));

// filter + projection
Expand Down Expand Up @@ -977,3 +978,29 @@ function testWithLevel1NestedPaths() {
'foo.one': string | null | undefined
}>({} as Test2);
}

function gh14764TestFilterQueryRestrictions() {
const TestModel = model<{ validKey: number }>('Test', new Schema({}));
// @ts-expect-error: A key not in the schema should be invalid
TestModel.find({ invalidKey: 0 });
// @ts-expect-error: A key not in the schema should be invalid for simple root operators
TestModel.find({ $and: [{ invalidKey: 0 }] });

// Any "nested" keys should be valid
TestModel.find({ 'validKey.subkey': 0 });

// And deeply "nested" keys should be valid
TestModel.find({ 'validKey.deep.nested.key': 0 });
TestModel.find({ validKey: { deep: { nested: { key: 0 } } } });

// Any Query should be accepted as the root argument (due to merge support)
TestModel.find(TestModel.find());
// @ts-expect-error: A Query should not be a valid type for a FilterQuery within an op like $and
TestModel.find({ $and: [TestModel.find()] });

const id = new Types.ObjectId();
// Any ObjectId should be accepted as the root argument
TestModel.find(id);
// @ts-expect-error: A ObjectId should not be a valid type for a FilterQuery within an op like $and
TestModel.find({ $and: [id] });
}
72 changes: 36 additions & 36 deletions types/models.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ declare module 'mongoose' {

export interface ReplaceOneModel<TSchema = AnyObject> {
/** The filter to limit the replaced document. */
filter: FilterQuery<TSchema>;
filter: RootFilterQuery<TSchema>;
/** The document with which to replace the matched document. */
replacement: mongodb.WithoutId<TSchema>;
/** Specifies a collation. */
Expand All @@ -203,7 +203,7 @@ declare module 'mongoose' {

export interface UpdateOneModel<TSchema = AnyObject> {
/** The filter to limit the updated documents. */
filter: FilterQuery<TSchema>;
filter: RootFilterQuery<TSchema>;
/** A document or pipeline containing update operators. */
update: UpdateQuery<TSchema>;
/** A set of filters specifying to which array elements an update should apply. */
Expand All @@ -220,7 +220,7 @@ declare module 'mongoose' {

export interface UpdateManyModel<TSchema = AnyObject> {
/** The filter to limit the updated documents. */
filter: FilterQuery<TSchema>;
filter: RootFilterQuery<TSchema>;
/** A document or pipeline containing update operators. */
update: UpdateQuery<TSchema>;
/** A set of filters specifying to which array elements an update should apply. */
Expand All @@ -237,7 +237,7 @@ declare module 'mongoose' {

export interface DeleteOneModel<TSchema = AnyObject> {
/** The filter to limit the deleted documents. */
filter: FilterQuery<TSchema>;
filter: RootFilterQuery<TSchema>;
/** Specifies a collation. */
collation?: mongodb.CollationOptions;
/** The index to use. If specified, then the query system will only consider plans using the hinted index. */
Expand All @@ -246,7 +246,7 @@ declare module 'mongoose' {

export interface DeleteManyModel<TSchema = AnyObject> {
/** The filter to limit the deleted documents. */
filter: FilterQuery<TSchema>;
filter: RootFilterQuery<TSchema>;
/** Specifies a collation. */
collation?: mongodb.CollationOptions;
/** The index to use. If specified, then the query system will only consider plans using the hinted index. */
Expand Down Expand Up @@ -318,7 +318,7 @@ declare module 'mongoose' {

/** Creates a `countDocuments` query: counts the number of documents that match `filter`. */
countDocuments(
filter?: FilterQuery<TRawDocType>,
filter?: RootFilterQuery<TRawDocType>,
options?: (mongodb.CountOptions & MongooseBaseQueryOptions<TRawDocType>) | null
): QueryWithHelpers<
number,
Expand Down Expand Up @@ -357,7 +357,7 @@ declare module 'mongoose' {
* regardless of the `single` option.
*/
deleteMany(
filter?: FilterQuery<TRawDocType>,
filter?: RootFilterQuery<TRawDocType>,
options?: (mongodb.DeleteOptions & MongooseBaseQueryOptions<TRawDocType>) | null
): QueryWithHelpers<
mongodb.DeleteResult,
Expand All @@ -368,7 +368,7 @@ declare module 'mongoose' {
TInstanceMethods
>;
deleteMany(
filter: FilterQuery<TRawDocType>
filter: RootFilterQuery<TRawDocType>
): QueryWithHelpers<
mongodb.DeleteResult,
THydratedDocumentType,
Expand All @@ -384,7 +384,7 @@ declare module 'mongoose' {
* `single` option.
*/
deleteOne(
filter?: FilterQuery<TRawDocType>,
filter?: RootFilterQuery<TRawDocType>,
options?: (mongodb.DeleteOptions & MongooseBaseQueryOptions<TRawDocType>) | null
): QueryWithHelpers<
mongodb.DeleteResult,
Expand All @@ -395,7 +395,7 @@ declare module 'mongoose' {
TInstanceMethods
>;
deleteOne(
filter: FilterQuery<TRawDocType>
filter: RootFilterQuery<TRawDocType>
): QueryWithHelpers<
mongodb.DeleteResult,
THydratedDocumentType,
Expand Down Expand Up @@ -446,7 +446,7 @@ declare module 'mongoose' {

/** Finds one document. */
findOne<ResultDoc = THydratedDocumentType>(
filter: FilterQuery<TRawDocType>,
filter: RootFilterQuery<TRawDocType>,
projection: ProjectionType<TRawDocType> | null | undefined,
options: QueryOptions<TRawDocType> & { lean: true }
): QueryWithHelpers<
Expand All @@ -458,16 +458,16 @@ declare module 'mongoose' {
TInstanceMethods
>;
findOne<ResultDoc = THydratedDocumentType>(
filter?: FilterQuery<TRawDocType>,
filter?: RootFilterQuery<TRawDocType>,
projection?: ProjectionType<TRawDocType> | null,
options?: QueryOptions<TRawDocType> | null
): QueryWithHelpers<ResultDoc | null, ResultDoc, TQueryHelpers, TRawDocType, 'findOne', TInstanceMethods>;
findOne<ResultDoc = THydratedDocumentType>(
filter?: FilterQuery<TRawDocType>,
filter?: RootFilterQuery<TRawDocType>,
projection?: ProjectionType<TRawDocType> | null
): QueryWithHelpers<ResultDoc | null, ResultDoc, TQueryHelpers, TRawDocType, 'findOne', TInstanceMethods>;
findOne<ResultDoc = THydratedDocumentType>(
filter?: FilterQuery<TRawDocType>
filter?: RootFilterQuery<TRawDocType>
): QueryWithHelpers<ResultDoc | null, ResultDoc, TQueryHelpers, TRawDocType, 'findOne', TInstanceMethods>;

/**
Expand Down Expand Up @@ -621,7 +621,7 @@ declare module 'mongoose' {
/** Creates a `distinct` query: returns the distinct values of the given `field` that match `filter`. */
distinct<DocKey extends string, ResultType = unknown>(
field: DocKey,
filter?: FilterQuery<TRawDocType>
filter?: RootFilterQuery<TRawDocType>
): QueryWithHelpers<
Array<
DocKey extends keyof WithLevel1NestedPaths<TRawDocType>
Expand Down Expand Up @@ -650,7 +650,7 @@ declare module 'mongoose' {
* the given `filter`, and `null` otherwise.
*/
exists(
filter: FilterQuery<TRawDocType>
filter: RootFilterQuery<TRawDocType>
): QueryWithHelpers<
{ _id: InferId<TRawDocType> } | null,
THydratedDocumentType,
Expand All @@ -662,7 +662,7 @@ declare module 'mongoose' {

/** Creates a `find` query: gets a list of documents that match `filter`. */
find<ResultDoc = THydratedDocumentType>(
filter: FilterQuery<TRawDocType>,
filter: RootFilterQuery<TRawDocType>,
projection: ProjectionType<TRawDocType> | null | undefined,
options: QueryOptions<TRawDocType> & { lean: true }
): QueryWithHelpers<
Expand All @@ -674,16 +674,16 @@ declare module 'mongoose' {
TInstanceMethods
>;
find<ResultDoc = THydratedDocumentType>(
filter: FilterQuery<TRawDocType>,
filter: RootFilterQuery<TRawDocType>,
projection?: ProjectionType<TRawDocType> | null | undefined,
options?: QueryOptions<TRawDocType> | null | undefined
): QueryWithHelpers<Array<ResultDoc>, ResultDoc, TQueryHelpers, TRawDocType, 'find', TInstanceMethods>;
find<ResultDoc = THydratedDocumentType>(
filter: FilterQuery<TRawDocType>,
filter: RootFilterQuery<TRawDocType>,
projection?: ProjectionType<TRawDocType> | null | undefined
): QueryWithHelpers<Array<ResultDoc>, ResultDoc, TQueryHelpers, TRawDocType, 'find', TInstanceMethods>;
find<ResultDoc = THydratedDocumentType>(
filter: FilterQuery<TRawDocType>
filter: RootFilterQuery<TRawDocType>
): QueryWithHelpers<Array<ResultDoc>, ResultDoc, TQueryHelpers, TRawDocType, 'find', TInstanceMethods>;
find<ResultDoc = THydratedDocumentType>(
): QueryWithHelpers<Array<ResultDoc>, ResultDoc, TQueryHelpers, TRawDocType, 'find', TInstanceMethods>;
Expand Down Expand Up @@ -711,7 +711,7 @@ declare module 'mongoose' {

/** Creates a `findOneAndUpdate` query, filtering by the given `_id`. */
findByIdAndUpdate<ResultDoc = THydratedDocumentType>(
filter: FilterQuery<TRawDocType>,
filter: RootFilterQuery<TRawDocType>,
update: UpdateQuery<TRawDocType>,
options: QueryOptions<TRawDocType> & { includeResultMetadata: true, lean: true }
): QueryWithHelpers<
Expand Down Expand Up @@ -756,7 +756,7 @@ declare module 'mongoose' {

/** Creates a `findOneAndDelete` query: atomically finds the given document, deletes it, and returns the document as it was before deletion. */
findOneAndDelete<ResultDoc = THydratedDocumentType>(
filter: FilterQuery<TRawDocType>,
filter: RootFilterQuery<TRawDocType>,
options: QueryOptions<TRawDocType> & { lean: true }
): QueryWithHelpers<
GetLeanResultType<TRawDocType, TRawDocType, 'findOneAndDelete'> | null,
Expand All @@ -767,17 +767,17 @@ declare module 'mongoose' {
TInstanceMethods
>;
findOneAndDelete<ResultDoc = THydratedDocumentType>(
filter: FilterQuery<TRawDocType>,
filter: RootFilterQuery<TRawDocType>,
options: QueryOptions<TRawDocType> & { includeResultMetadata: true }
): QueryWithHelpers<ModifyResult<ResultDoc>, ResultDoc, TQueryHelpers, TRawDocType, 'findOneAndDelete', TInstanceMethods>;
findOneAndDelete<ResultDoc = THydratedDocumentType>(
filter?: FilterQuery<TRawDocType> | null,
filter?: RootFilterQuery<TRawDocType> | null,
options?: QueryOptions<TRawDocType> | null
): QueryWithHelpers<ResultDoc | null, ResultDoc, TQueryHelpers, TRawDocType, 'findOneAndDelete', TInstanceMethods>;

/** Creates a `findOneAndReplace` query: atomically finds the given document and replaces it with `replacement`. */
findOneAndReplace<ResultDoc = THydratedDocumentType>(
filter: FilterQuery<TRawDocType>,
filter: RootFilterQuery<TRawDocType>,
replacement: TRawDocType | AnyObject,
options: QueryOptions<TRawDocType> & { lean: true }
): QueryWithHelpers<
Expand All @@ -789,24 +789,24 @@ declare module 'mongoose' {
TInstanceMethods
>;
findOneAndReplace<ResultDoc = THydratedDocumentType>(
filter: FilterQuery<TRawDocType>,
filter: RootFilterQuery<TRawDocType>,
replacement: TRawDocType | AnyObject,
options: QueryOptions<TRawDocType> & { includeResultMetadata: true }
): QueryWithHelpers<ModifyResult<ResultDoc>, ResultDoc, TQueryHelpers, TRawDocType, 'findOneAndReplace', TInstanceMethods>;
findOneAndReplace<ResultDoc = THydratedDocumentType>(
filter: FilterQuery<TRawDocType>,
filter: RootFilterQuery<TRawDocType>,
replacement: TRawDocType | AnyObject,
options: QueryOptions<TRawDocType> & { upsert: true } & ReturnsNewDoc
): QueryWithHelpers<ResultDoc, ResultDoc, TQueryHelpers, TRawDocType, 'findOneAndReplace', TInstanceMethods>;
findOneAndReplace<ResultDoc = THydratedDocumentType>(
filter?: FilterQuery<TRawDocType>,
filter?: RootFilterQuery<TRawDocType>,
replacement?: TRawDocType | AnyObject,
options?: QueryOptions<TRawDocType> | null
): QueryWithHelpers<ResultDoc | null, ResultDoc, TQueryHelpers, TRawDocType, 'findOneAndReplace', TInstanceMethods>;

/** Creates a `findOneAndUpdate` query: atomically find the first document that matches `filter` and apply `update`. */
findOneAndUpdate<ResultDoc = THydratedDocumentType>(
filter: FilterQuery<TRawDocType>,
filter: RootFilterQuery<TRawDocType>,
update: UpdateQuery<TRawDocType>,
options: QueryOptions<TRawDocType> & { includeResultMetadata: true, lean: true }
): QueryWithHelpers<
Expand All @@ -818,7 +818,7 @@ declare module 'mongoose' {
TInstanceMethods
>;
findOneAndUpdate<ResultDoc = THydratedDocumentType>(
filter: FilterQuery<TRawDocType>,
filter: RootFilterQuery<TRawDocType>,
update: UpdateQuery<TRawDocType>,
options: QueryOptions<TRawDocType> & { lean: true }
): QueryWithHelpers<
Expand All @@ -830,24 +830,24 @@ declare module 'mongoose' {
TInstanceMethods
>;
findOneAndUpdate<ResultDoc = THydratedDocumentType>(
filter: FilterQuery<TRawDocType>,
filter: RootFilterQuery<TRawDocType>,
update: UpdateQuery<TRawDocType>,
options: QueryOptions<TRawDocType> & { includeResultMetadata: true }
): QueryWithHelpers<ModifyResult<ResultDoc>, ResultDoc, TQueryHelpers, TRawDocType, 'findOneAndUpdate', TInstanceMethods>;
findOneAndUpdate<ResultDoc = THydratedDocumentType>(
filter: FilterQuery<TRawDocType>,
filter: RootFilterQuery<TRawDocType>,
update: UpdateQuery<TRawDocType>,
options: QueryOptions<TRawDocType> & { upsert: true } & ReturnsNewDoc
): QueryWithHelpers<ResultDoc, ResultDoc, TQueryHelpers, TRawDocType, 'findOneAndUpdate', TInstanceMethods>;
findOneAndUpdate<ResultDoc = THydratedDocumentType>(
filter?: FilterQuery<TRawDocType>,
filter?: RootFilterQuery<TRawDocType>,
update?: UpdateQuery<TRawDocType>,
options?: QueryOptions<TRawDocType> | null
): QueryWithHelpers<ResultDoc | null, ResultDoc, TQueryHelpers, TRawDocType, 'findOneAndUpdate', TInstanceMethods>;

/** Creates a `replaceOne` query: finds the first document that matches `filter` and replaces it with `replacement`. */
replaceOne<ResultDoc = THydratedDocumentType>(
filter?: FilterQuery<TRawDocType>,
filter?: RootFilterQuery<TRawDocType>,
replacement?: TRawDocType | AnyObject,
options?: (mongodb.ReplaceOptions & MongooseQueryOptions<TRawDocType>) | null
): QueryWithHelpers<UpdateWriteOpResult, ResultDoc, TQueryHelpers, TRawDocType, 'replaceOne', TInstanceMethods>;
Expand All @@ -860,14 +860,14 @@ declare module 'mongoose' {

/** Creates a `updateMany` query: updates all documents that match `filter` with `update`. */
updateMany<ResultDoc = THydratedDocumentType>(
filter?: FilterQuery<TRawDocType>,
filter?: RootFilterQuery<TRawDocType>,
update?: UpdateQuery<TRawDocType> | UpdateWithAggregationPipeline,
options?: (mongodb.UpdateOptions & MongooseUpdateQueryOptions<TRawDocType>) | null
): QueryWithHelpers<UpdateWriteOpResult, ResultDoc, TQueryHelpers, TRawDocType, 'updateMany', TInstanceMethods>;

/** Creates a `updateOne` query: updates the first document that matches `filter` with `update`. */
updateOne<ResultDoc = THydratedDocumentType>(
filter?: FilterQuery<TRawDocType>,
filter?: RootFilterQuery<TRawDocType>,
update?: UpdateQuery<TRawDocType> | UpdateWithAggregationPipeline,
options?: (mongodb.UpdateOptions & MongooseUpdateQueryOptions<TRawDocType>) | null
): QueryWithHelpers<UpdateWriteOpResult, ResultDoc, TQueryHelpers, TRawDocType, 'updateOne', TInstanceMethods>;
Expand Down
Loading

0 comments on commit ea2a4ef

Please sign in to comment.