diff --git a/lib/model.js b/lib/model.js index 320ea334153..a6743f87d3d 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1451,6 +1451,17 @@ Model.createCollection = async function createCollection(options) { * // Will drop the 'age' index and create an index on `name` * await Customer.syncIndexes(); * + * You should be careful about running `syncIndexes()` on production applications under heavy load, + * because index builds are expensive operations, and unexpected index drops can lead to degraded + * performance. Before running `syncIndexes()`, you can use the [`diffIndexes()` function](#Model.diffIndexes()) + * to check what indexes `syncIndexes()` will drop and create. + * + * #### Example: + * + * const { toDrop, toCreate } = await Model.diffIndexes(); + * toDrop; // Array of strings containing names of indexes that `syncIndexes()` will drop + * toCreate; // Array of strings containing names of indexes that `syncIndexes()` will create + * * @param {Object} [options] options to pass to `ensureIndexes()` * @param {Boolean} [options.background=null] if specified, overrides each index's `background` property * @return {Promise} @@ -1483,9 +1494,14 @@ Model.syncIndexes = async function syncIndexes(options) { /** * Does a dry-run of `Model.syncIndexes()`, returning the indexes that `syncIndexes()` would drop and create if you were to run `syncIndexes()`. * + * #### Example: + * + * const { toDrop, toCreate } = await Model.diffIndexes(); + * toDrop; // Array of strings containing names of indexes that `syncIndexes()` will drop + * toCreate; // Array of strings containing names of indexes that `syncIndexes()` will create + * * @param {Object} [options] - * @returns {Promise} which contains an object, {toDrop, toCreate}, which - * are indexes that would be dropped in MongoDB and indexes that would be created in MongoDB. + * @return {Promise} contains the indexes that would be dropped in MongoDB and indexes that would be created in MongoDB as `{ toDrop: string[], toCreate: string[] }`. */ Model.diffIndexes = async function diffIndexes() { diff --git a/test/types/schema.test.ts b/test/types/schema.test.ts index 16f58ed938b..fc0204e2a71 100644 --- a/test/types/schema.test.ts +++ b/test/types/schema.test.ts @@ -1218,3 +1218,15 @@ function gh13800() { expectError(this.someOtherField); }); } + +async function gh13797() { + interface IUser { + name: string; + } + new Schema({ name: { type: String, required: function() { + expectType(this); return true; + } } }); + new Schema({ name: { type: String, default: function() { + expectType(this); return ''; + } } }); +} diff --git a/types/index.d.ts b/types/index.d.ts index 840a3634e16..1bd4b0a7085 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -236,7 +236,7 @@ declare module 'mongoose' { /** * Create a new schema */ - constructor(definition?: SchemaDefinition> | DocType, options?: SchemaOptions | ResolveSchemaOptions); + constructor(definition?: SchemaDefinition, EnforcedDocType> | DocType, options?: SchemaOptions | ResolveSchemaOptions); /** Adds key path / schema type pairs to this schema. */ add(obj: SchemaDefinition> | Schema, prefix?: string): this; @@ -300,7 +300,7 @@ declare module 'mongoose' { methods: { [F in keyof TInstanceMethods]: TInstanceMethods[F] } & AnyObject; /** The original object passed to the schema constructor */ - obj: SchemaDefinition>; + obj: SchemaDefinition, EnforcedDocType>; /** Gets/sets schema paths. */ path>(path: string): ResultType; @@ -484,26 +484,26 @@ declare module 'mongoose' { ? DateSchemaDefinition : (Function | string); - export type SchemaDefinitionProperty = SchemaDefinitionWithBuiltInClass | - SchemaTypeOptions | + export type SchemaDefinitionProperty = SchemaDefinitionWithBuiltInClass | + SchemaTypeOptions | typeof SchemaType | Schema | Schema[] | - SchemaTypeOptions>[] | + SchemaTypeOptions, EnforcedDocType>[] | Function[] | - SchemaDefinition | - SchemaDefinition>[] | + SchemaDefinition | + SchemaDefinition, EnforcedDocType>[] | typeof Schema.Types.Mixed | - MixedSchemaTypeOptions; + MixedSchemaTypeOptions; - export type SchemaDefinition = T extends undefined + export type SchemaDefinition = T extends undefined ? { [path: string]: SchemaDefinitionProperty; } - : { [path in keyof T]?: SchemaDefinitionProperty; }; + : { [path in keyof T]?: SchemaDefinitionProperty; }; export type AnyArray = T[] | ReadonlyArray; export type ExtractMongooseArray = T extends Types.Array ? AnyArray> : T; - export interface MixedSchemaTypeOptions extends SchemaTypeOptions { + export interface MixedSchemaTypeOptions extends SchemaTypeOptions { type: typeof Schema.Types.Mixed; } diff --git a/types/schematypes.d.ts b/types/schematypes.d.ts index 5f7514a8e03..088bc27c598 100644 --- a/types/schematypes.d.ts +++ b/types/schematypes.d.ts @@ -39,7 +39,7 @@ declare module 'mongoose' { type DefaultType = T extends Schema.Types.Mixed ? any : Partial>; - class SchemaTypeOptions { + class SchemaTypeOptions { type?: T extends string ? StringSchemaDefinition : T extends number ? NumberSchemaDefinition : @@ -48,12 +48,12 @@ declare module 'mongoose' { T extends Map ? SchemaDefinition : T extends Buffer ? SchemaDefinition : T extends Types.ObjectId ? ObjectIdSchemaDefinition : - T extends Types.ObjectId[] ? AnyArray | AnyArray> : - T extends object[] ? (AnyArray> | AnyArray>> | AnyArray>>) : - T extends string[] ? AnyArray | AnyArray> : - T extends number[] ? AnyArray | AnyArray> : - T extends boolean[] ? AnyArray | AnyArray> : - T extends Function[] ? AnyArray | AnyArray>> : + T extends Types.ObjectId[] ? AnyArray | AnyArray> : + T extends object[] ? (AnyArray> | AnyArray>> | AnyArray, EnforcedDocType>>) : + T extends string[] ? AnyArray | AnyArray> : + T extends number[] ? AnyArray | AnyArray> : + T extends boolean[] ? AnyArray | AnyArray> : + T extends Function[] ? AnyArray | AnyArray, EnforcedDocType>> : T | typeof SchemaType | Schema | SchemaDefinition | Function | AnyArray; /** Defines a virtual with the given name that gets/sets this path. */ @@ -74,13 +74,13 @@ declare module 'mongoose' { * path cannot be set to a nullish value. If a function, Mongoose calls the * function and only checks for nullish values if the function returns a truthy value. */ - required?: boolean | (() => boolean) | [boolean, string] | [() => boolean, string]; + required?: boolean | ((this: EnforcedDocType) => boolean) | [boolean, string] | [(this: EnforcedDocType) => boolean, string]; /** * The default value for this path. If a function, Mongoose executes the function * and uses the return value as the default. */ - default?: DefaultType | ((this: any, doc: any) => DefaultType) | null; + default?: DefaultType | ((this: EnforcedDocType, doc: any) => DefaultType) | null; /** * The model that `populate()` should use if populating this path.