diff --git a/src/bulk/common.ts b/src/bulk/common.ts index 078b122c5c..0e782b5702 100644 --- a/src/bulk/common.ts +++ b/src/bulk/common.ts @@ -87,8 +87,12 @@ export interface ReplaceOneModel { export interface UpdateOneModel { /** The filter to limit the updated documents. */ filter: Filter; - /** A document or pipeline containing update operators. */ - update: UpdateFilter | UpdateFilter[]; + /** + * The modifications to apply. The value can be either: + * UpdateFilter - A document that contains update operator expressions, + * Document[] - an aggregation pipeline. + */ + update: UpdateFilter | Document[]; /** A set of filters specifying to which array elements an update should apply. */ arrayFilters?: Document[]; /** Specifies a collation. */ @@ -103,8 +107,12 @@ export interface UpdateOneModel { export interface UpdateManyModel { /** The filter to limit the updated documents. */ filter: Filter; - /** A document or pipeline containing update operators. */ - update: UpdateFilter | UpdateFilter[]; + /** + * The modifications to apply. The value can be either: + * UpdateFilter - A document that contains update operator expressions, + * Document[] - an aggregation pipeline. + */ + update: UpdateFilter | Document[]; /** A set of filters specifying to which array elements an update should apply. */ arrayFilters?: Document[]; /** Specifies a collation. */ diff --git a/src/collection.ts b/src/collection.ts index d12bbe31ee..a735a3a082 100644 --- a/src/collection.ts +++ b/src/collection.ts @@ -339,13 +339,17 @@ export class Collection { /** * Update a single document in a collection * + * The value of `update` can be either: + * - UpdateFilter - A document that contains update operator expressions, + * - Document[] - an aggregation pipeline. + * * @param filter - The filter used to select the document to update - * @param update - The update operations to be applied to the document + * @param update - The modifications to apply * @param options - Optional settings for the command */ async updateOne( filter: Filter, - update: UpdateFilter | Partial, + update: UpdateFilter | Document[], options?: UpdateOptions ): Promise> { return executeOperation( @@ -385,13 +389,17 @@ export class Collection { /** * Update multiple documents in a collection * - * @param filter - The filter used to select the documents to update - * @param update - The update operations to be applied to the documents + * The value of `update` can be either: + * - UpdateFilter - A document that contains update operator expressions, + * - Document[] - an aggregation pipeline. + * + * @param filter - The filter used to select the document to update + * @param update - The modifications to apply * @param options - Optional settings for the command */ async updateMany( filter: Filter, - update: UpdateFilter, + update: UpdateFilter | Document[], options?: UpdateOptions ): Promise> { return executeOperation( diff --git a/src/mongo_types.ts b/src/mongo_types.ts index 5682ecf878..f201a50eb6 100644 --- a/src/mongo_types.ts +++ b/src/mongo_types.ts @@ -243,7 +243,11 @@ export type SetFields = ({ readonly [key in KeysOfAType | undefined>]?: | OptionalId> | AddToSetOperators>>>; -} & NotAcceptedFields | undefined>) & { +} & IsAny< + TSchema[keyof TSchema], + object, + NotAcceptedFields | undefined> +>) & { readonly [key: string]: AddToSetOperators | any; }; diff --git a/test/types/community/collection/bulkWrite.test-d.ts b/test/types/community/collection/bulkWrite.test-d.ts index 5c8ee78ecf..f47044eb92 100644 --- a/test/types/community/collection/bulkWrite.test-d.ts +++ b/test/types/community/collection/bulkWrite.test-d.ts @@ -1,6 +1,6 @@ import { expectError } from 'tsd'; -import { MongoClient, ObjectId } from '../../../mongodb'; +import { type Collection, type Document, MongoClient, ObjectId } from '../../../mongodb'; // TODO(NODE-3347): Improve these tests to use more expect assertions @@ -297,3 +297,197 @@ collectionType.bulkWrite([ } } ]); + +{ + // NODE-5647 - Type error with $addToSet in bulkWrite + interface TestDocument { + readonly myId: number; + readonly mySet: number[]; + readonly myAny: any; + } + const collection = undefined as unknown as Collection; + expectError( + collection.bulkWrite([ + { + updateOne: { + filter: { myId: 0 }, + update: { + $addToSet: { mySet: 'value of other type' } + } + } + } + ]) + ); + collection.bulkWrite([ + { + updateOne: { + filter: { myId: 0 }, + update: { + $addToSet: { mySet: 0 } + } + } + } + ]); + collection.bulkWrite([ + { + updateOne: { + filter: { myId: 0 }, + update: { + $addToSet: { myAny: 1 } + } + } + } + ]); + collection.bulkWrite([ + { + updateOne: { + filter: { myId: 0 }, + update: [ + { + $addToSet: { myAny: 0 } + } + ] + } + } + ]); + expectError( + collection.bulkWrite([ + { + updateMany: { + filter: { myId: 0 }, + update: { + $addToSet: { mySet: 'value of other type' } + } + } + } + ]) + ); + collection.bulkWrite([ + { + updateMany: { + filter: { myId: 0 }, + update: { + $addToSet: { mySet: 0 } + } + } + } + ]); + collection.bulkWrite([ + { + updateMany: { + filter: { myId: 0 }, + update: { + $addToSet: { myAny: 1 } + } + } + } + ]); + collection.bulkWrite([ + { + updateMany: { + filter: { myId: 0 }, + update: [ + { + $addToSet: { mySet: 0 } + } + ] + } + } + ]); + + interface IndexSingatureTestDocument extends Document { + readonly myId: number; + readonly mySet: number[]; + } + const indexSingatureCollection = undefined as unknown as Collection; + indexSingatureCollection.bulkWrite([ + { + updateOne: { + filter: { myId: 0 }, + update: { + $addToSet: { mySet: 0 } + } + } + } + ]); + indexSingatureCollection.bulkWrite([ + { + updateOne: { + filter: { myId: 0 }, + update: [ + { + $addToSet: { mySet: 0 } + } + ] + } + } + ]); + indexSingatureCollection.bulkWrite([ + { + updateMany: { + filter: { myId: 0 }, + update: { + $addToSet: { mySet: 0 } + } + } + } + ]); + indexSingatureCollection.bulkWrite([ + { + updateMany: { + filter: { myId: 0 }, + update: [ + { + $addToSet: { mySet: 0 } + } + ] + } + } + ]); + + const collectionOfAnyType = undefined as unknown as Collection; + collectionOfAnyType.bulkWrite([ + { + updateOne: { + filter: { myId: 0 }, + update: { + $addToSet: { mySet: 0 } + } + } + } + ]); + collectionOfAnyType.bulkWrite([ + { + updateOne: { + filter: { myId: 0 }, + update: [ + { + $addToSet: { mySet: 0 } + } + ] + } + } + ]); + collectionOfAnyType.bulkWrite([ + { + updateMany: { + filter: { myId: 0 }, + update: { + $addToSet: { mySet: 0 } + } + } + } + ]); + collectionOfAnyType.bulkWrite([ + { + updateMany: { + filter: { myId: 0 }, + update: [ + { + $addToSet: { mySet: 0 } + } + ] + } + } + ]); +} diff --git a/test/types/community/collection/updateX.test-d.ts b/test/types/community/collection/updateX.test-d.ts index b729b20b4d..5ea59cd525 100644 --- a/test/types/community/collection/updateX.test-d.ts +++ b/test/types/community/collection/updateX.test-d.ts @@ -439,3 +439,66 @@ export async function testPushWithId(): Promise { collectionWithSchema.updateMany({}, {}) ); } + +{ + // NODE-5647 - Type error with $addToSet in bulkWrite + interface TestDocument { + readonly myId: number; + readonly mySet: number[]; + readonly myAny: any; + } + const collection = undefined as unknown as Collection; + expectError(collection.updateOne({ myId: 0 }, { $addToSet: { mySet: 'value of other type' } })); + collection.updateOne({ myId: 0 }, { $addToSet: { mySet: 0 } }); + collection.updateOne({ myId: 0 }, { $addToSet: { myAny: 1 } }); + collection.updateOne({ myId: 0 }, [ + { + $addToSet: { mySet: 0 } + } + ]); + expectError(collection.updateMany({ myId: 0 }, { $addToSet: { mySet: 'value of other type' } })); + collection.updateMany({ myId: 0 }, { $addToSet: { mySet: 0 } }); + collection.updateMany({ myId: 0 }, { $addToSet: { myAny: 1 } }); + collection.updateMany({ myId: 0 }, [ + { + $addToSet: { mySet: 0 } + } + ]); + + interface IndexSingatureTestDocument extends Document { + readonly myId: number; + readonly mySet: number[]; + readonly myAny: any; + } + const indexSingatureCollection = undefined as unknown as Collection; + indexSingatureCollection.updateOne({ myId: 0 }, { $addToSet: { mySet: 0 } }); + indexSingatureCollection.updateOne({ myId: 0 }, { $addToSet: { myAny: 1 } }); + indexSingatureCollection.updateOne({ myId: 0 }, [ + { + $addToSet: { mySet: 0 } + } + ]); + indexSingatureCollection.updateMany({ myId: 0 }, { $addToSet: { mySet: 0 } }); + indexSingatureCollection.updateMany({ myId: 0 }, { $addToSet: { myAny: 1 } }); + indexSingatureCollection.updateMany({ myId: 0 }, [ + { + $addToSet: { mySet: 0 } + } + ]); + + const collectionOfAnyType = undefined as unknown as Collection; + collectionOfAnyType.updateOne({ myId: 0 }, { $addToSet: { mySet: 0 } }); + collectionOfAnyType.updateOne({ myId: 0 }, { $addToSet: { myAny: 1 } }); + collectionOfAnyType.updateOne({ myId: 0 }, [ + { + $addToSet: { mySet: 0 } + } + ]); + collectionOfAnyType.updateMany({ myId: 0 }, { $addToSet: { mySet: 0 } }); + collectionOfAnyType.updateMany({ myId: 0 }, { $addToSet: { myAny: 1 } }); + collectionOfAnyType.updateMany({ myId: 0 }, [ + { + $addToSet: { mySet: 0 } + } + ]); +}