Skip to content

Commit

Permalink
fix(index.d.ts): make $pull more permissive to allow dotted paths
Browse files Browse the repository at this point in the history
Fix #9993
  • Loading branch information
vkarpov15 committed Mar 11, 2021
1 parent c9d6c3a commit b3eced2
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 2 deletions.
45 changes: 44 additions & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2234,7 +2234,50 @@ declare module 'mongoose' {

export type FilterQuery<T> = _FilterQuery<DocumentDefinition<T>>;

export type UpdateQuery<T> = mongodb.UpdateQuery<DocumentDefinition<T>> & mongodb.MatchKeysAndValues<DocumentDefinition<T>>;
type NumericTypes = number | mongodb.Decimal128 | mongodb.Double | mongodb.Int32 | mongodb.Long;

type KeysOfAType<TSchema, Type> = {
[key in keyof TSchema]: NonNullable<TSchema[key]> extends Type ? key : never;
}[keyof TSchema];

type PullOperator<TSchema> = {
[key in KeysOfAType<TSchema, ReadonlyArray<any>>]?:
| Partial<Unpacked<TSchema[key]>>
| mongodb.ObjectQuerySelector<Unpacked<TSchema[key]>>
// 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>
| any;
};

/** @see https://docs.mongodb.com/manual/reference/operator/update */
type _UpdateQuery<TSchema> = {
/** @see https://docs.mongodb.com/manual/reference/operator/update-field/ */
$currentDate?: mongodb.OnlyFieldsOfType<TSchema, Date | mongodb.Timestamp, true | { $type: 'date' | 'timestamp' }>;
$inc?: mongodb.OnlyFieldsOfType<TSchema, NumericTypes | undefined>;
$min?: mongodb.MatchKeysAndValues<TSchema>;
$max?: mongodb.MatchKeysAndValues<TSchema>;
$mul?: mongodb.OnlyFieldsOfType<TSchema, NumericTypes | undefined>;
$rename?: { [key: string]: string };
$set?: mongodb.MatchKeysAndValues<TSchema>;
$setOnInsert?: mongodb.MatchKeysAndValues<TSchema>;
$unset?: mongodb.OnlyFieldsOfType<TSchema, any, '' | 1 | true>;

/** @see https://docs.mongodb.com/manual/reference/operator/update-array/ */
$addToSet?: mongodb.SetFields<TSchema>;
$pop?: mongodb.OnlyFieldsOfType<TSchema, ReadonlyArray<any>, 1 | -1>;
$pull?: PullOperator<TSchema>;
$push?: mongodb.PushOperator<TSchema>;
$pullAll?: mongodb.PullAllOperator<TSchema>;

/** @see https://docs.mongodb.com/manual/reference/operator/update-bitwise/ */
$bit?: {
[key: string]: { [key in 'and' | 'or' | 'xor']?: number };
};
};

export type UpdateQuery<T> = _UpdateQuery<DocumentDefinition<T>> & mongodb.MatchKeysAndValues<DocumentDefinition<T>>;

type _AllowStringsForIds<T> = {
[K in keyof T]: [Extract<T[K], mongodb.ObjectId>] extends [never] ? T[K] : T[K] | string;
Expand Down
12 changes: 11 additions & 1 deletion test/typescript/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,26 @@ interface QueryHelpers {
byName(name: string): Query<Array<ITest>, ITest, QueryHelpers>;
}

const schema: Schema<ITest, Model<ITest>> = new Schema({ name: { type: 'String' }, tags: [String] });
const schema: Schema<ITest, Model<ITest>> = new Schema({
name: { type: 'String' },
tags: [String],
docs: [{ nested: { id: Number } }]
});

schema.query.byName = function(name: string): Query<Array<ITest>, 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<ITest, Model<ITest, QueryHelpers>>('Test', schema);
Expand Down Expand Up @@ -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<ITest | null, ITest> = Test.findOne();
query instanceof Query;
Expand Down

0 comments on commit b3eced2

Please sign in to comment.