diff --git a/index.d.ts b/index.d.ts index 367685660df..f9e4066e44f 100644 --- a/index.d.ts +++ b/index.d.ts @@ -2234,7 +2234,50 @@ declare module 'mongoose' { export type FilterQuery = _FilterQuery>; - export type UpdateQuery = mongodb.UpdateQuery> & mongodb.MatchKeysAndValues>; + type NumericTypes = number | mongodb.Decimal128 | mongodb.Double | mongodb.Int32 | mongodb.Long; + + type KeysOfAType = { + [key in keyof TSchema]: NonNullable extends Type ? key : never; + }[keyof TSchema]; + + type PullOperator = { + [key in KeysOfAType>]?: + | Partial> + | mongodb.ObjectQuerySelector> + // Doesn't look like TypeScript has good support for creating an + // object containing dotted keys: + // https://stackoverflow.com/questions/58434389/typescript-deep-keyof-of-a-nested-object + | mongodb.QuerySelector + | any; + }; + + /** @see https://docs.mongodb.com/manual/reference/operator/update */ + type _UpdateQuery = { + /** @see https://docs.mongodb.com/manual/reference/operator/update-field/ */ + $currentDate?: mongodb.OnlyFieldsOfType; + $inc?: mongodb.OnlyFieldsOfType; + $min?: mongodb.MatchKeysAndValues; + $max?: mongodb.MatchKeysAndValues; + $mul?: mongodb.OnlyFieldsOfType; + $rename?: { [key: string]: string }; + $set?: mongodb.MatchKeysAndValues; + $setOnInsert?: mongodb.MatchKeysAndValues; + $unset?: mongodb.OnlyFieldsOfType; + + /** @see https://docs.mongodb.com/manual/reference/operator/update-array/ */ + $addToSet?: mongodb.SetFields; + $pop?: mongodb.OnlyFieldsOfType, 1 | -1>; + $pull?: PullOperator; + $push?: mongodb.PushOperator; + $pullAll?: mongodb.PullAllOperator; + + /** @see https://docs.mongodb.com/manual/reference/operator/update-bitwise/ */ + $bit?: { + [key: string]: { [key in 'and' | 'or' | 'xor']?: number }; + }; + }; + + export type UpdateQuery = _UpdateQuery> & mongodb.MatchKeysAndValues>; type _AllowStringsForIds = { [K in keyof T]: [Extract] extends [never] ? T[K] : T[K] | string; diff --git a/test/typescript/queries.ts b/test/typescript/queries.ts index 1d67661cb17..0a559b7dede 100644 --- a/test/typescript/queries.ts +++ b/test/typescript/queries.ts @@ -4,17 +4,26 @@ interface QueryHelpers { byName(name: string): Query, ITest, QueryHelpers>; } -const schema: Schema> = new Schema({ name: { type: 'String' }, tags: [String] }); +const schema: Schema> = new Schema({ + name: { type: 'String' }, + tags: [String], + docs: [{ nested: { id: Number } }] +}); schema.query.byName = function(name: string): Query, ITest, QueryHelpers> { return this.find({ name }); }; +interface ISubdoc extends Document { + id?: number; +} + interface ITest extends Document { name?: string; age?: number; parent?: Types.ObjectId; tags?: string[]; + docs?: ISubdoc[]; } const Test = model>('Test', schema); @@ -58,6 +67,7 @@ Test.findOneAndReplace({ name: 'test' }, { _id: new Types.ObjectId(), name: 'tes Test.findOneAndUpdate({ name: 'test' }, { $addToSet: { tags: 'each' } }); Test.findOneAndUpdate({ name: 'test' }, { $push: { tags: 'each' } }); +Test.findOneAndUpdate({ name: 'test' }, { $pull: { docs: { 'nested.id': 1 } } }); const query: Query = Test.findOne(); query instanceof Query;