Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions test/types/middleware.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,3 +200,60 @@ function gh13601() {
expectAssignable<Document>(this);
});
}

function gh15242() {
type PostPersisted = {
title: string,
postTime: Date
};

type ValidatorThis = DocumentValidatorThis | QueryValidatorThis;
type DocumentValidatorThis = HydratedDocument<PostPersisted>;
type QueryValidatorThis = Query<PostRecord, PostRecord>;

const PostSchema = new Schema<PostPersisted>({
title: { type: String, required: true },
postTime: {
type: Date,
required: true,
validate: {
validator: async function(this: ValidatorThis, postTime: Date): Promise<boolean> {
return true;
}
}
}
});

type PostRecord = HydratedDocument<PostPersisted>;
const PostModel = model<PostPersisted>('Post', PostSchema);
}

function gh15242WithVirtuals() {
type PostPersisted = {
title: string,
postTime: Date
};

type ValidatorThis = DocumentValidatorThis | QueryValidatorThis;
type DocumentValidatorThis = HydratedDocument<PostPersisted, { myVirtual: number }>;
type QueryValidatorThis = Query<PostRecord, PostRecord>;

const PostSchema = new Schema({
title: { type: String, required: true },
postTime: {
type: Date,
required: true,
validate: {
validator: async function(this: ValidatorThis, postTime: Date): Promise<boolean> {
if (!(this instanceof Query)) {
expectType<number>(this.myVirtual);
}
return true;
}
}
}
}, { virtuals: { myVirtual: { get() { return 42; } } } });

type PostRecord = HydratedDocument<PostPersisted, { myVirtual: number }>;
const PostModel = model<PostPersisted>('Post', PostSchema);
}
32 changes: 16 additions & 16 deletions types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -273,10 +273,10 @@ declare module 'mongoose' {
/**
* Create a new schema
*/
constructor(definition?: SchemaDefinition<SchemaDefinitionType<RawDocType>, RawDocType> | DocType, options?: SchemaOptions<FlatRecord<DocType>, TInstanceMethods, TQueryHelpers, TStaticMethods, TVirtuals, THydratedDocumentType> | ResolveSchemaOptions<TSchemaOptions>);
constructor(definition?: SchemaDefinition<SchemaDefinitionType<RawDocType>, RawDocType, THydratedDocumentType> | DocType, options?: SchemaOptions<FlatRecord<DocType>, TInstanceMethods, TQueryHelpers, TStaticMethods, TVirtuals, THydratedDocumentType> | ResolveSchemaOptions<TSchemaOptions>);

/** Adds key path / schema type pairs to this schema. */
add(obj: SchemaDefinition<SchemaDefinitionType<RawDocType>> | Schema, prefix?: string): this;
add(obj: SchemaDefinition<SchemaDefinitionType<RawDocType>, RawDocType> | Schema, prefix?: string): this;

/**
* Add an alias for `path`. This means getting or setting the `alias`
Expand Down Expand Up @@ -541,21 +541,21 @@ declare module 'mongoose' {
? DateSchemaDefinition
: (Function | string);

export type SchemaDefinitionProperty<T = undefined, EnforcedDocType = any> = SchemaDefinitionWithBuiltInClass<T> |
SchemaTypeOptions<T extends undefined ? any : T, EnforcedDocType> |
typeof SchemaType |
Schema<any, any, any> |
Schema<any, any, any>[] |
SchemaTypeOptions<T extends undefined ? any : Unpacked<T>, EnforcedDocType>[] |
Function[] |
SchemaDefinition<T, EnforcedDocType> |
SchemaDefinition<Unpacked<T>, EnforcedDocType>[] |
typeof Schema.Types.Mixed |
MixedSchemaTypeOptions<EnforcedDocType>;

export type SchemaDefinition<T = undefined, EnforcedDocType = any> = T extends undefined
export type SchemaDefinitionProperty<T = undefined, EnforcedDocType = any, THydratedDocumentType = HydratedDocument<EnforcedDocType>> = SchemaDefinitionWithBuiltInClass<T>
| SchemaTypeOptions<T extends undefined ? any : T, EnforcedDocType, THydratedDocumentType>
| typeof SchemaType
| Schema<any, any, any>
| Schema<any, any, any>[]
| SchemaTypeOptions<T extends undefined ? any : Unpacked<T>, EnforcedDocType, THydratedDocumentType>[]
| Function[]
| SchemaDefinition<T, EnforcedDocType, THydratedDocumentType>
| SchemaDefinition<Unpacked<T>, EnforcedDocType, THydratedDocumentType>[]
| typeof Schema.Types.Mixed
| MixedSchemaTypeOptions<EnforcedDocType>;

export type SchemaDefinition<T = undefined, EnforcedDocType = any, THydratedDocumentType = HydratedDocument<EnforcedDocType>> = T extends undefined
? { [path: string]: SchemaDefinitionProperty; }
: { [path in keyof T]?: SchemaDefinitionProperty<T[path], EnforcedDocType>; };
: { [path in keyof T]?: SchemaDefinitionProperty<T[path], EnforcedDocType, THydratedDocumentType>; };

export type AnyArray<T> = T[] | ReadonlyArray<T>;
export type ExtractMongooseArray<T> = T extends Types.Array<any> ? AnyArray<Unpacked<T>> : T;
Expand Down
16 changes: 8 additions & 8 deletions types/schematypes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ declare module 'mongoose' {

type DefaultType<T> = T extends Schema.Types.Mixed ? any : Partial<ExtractMongooseArray<T>>;

class SchemaTypeOptions<T, EnforcedDocType = any> {
class SchemaTypeOptions<T, EnforcedDocType = any, THydratedDocumentType = HydratedDocument<EnforcedDocType>> {
type?:
T extends string ? StringSchemaDefinition :
T extends number ? NumberSchemaDefinition :
Expand All @@ -65,19 +65,19 @@ declare module 'mongoose' {
T extends Map<any, any> ? SchemaDefinition<typeof Map> :
T extends Buffer ? SchemaDefinition<typeof Buffer> :
T extends Types.ObjectId ? ObjectIdSchemaDefinition :
T extends Types.ObjectId[] ? AnyArray<ObjectIdSchemaDefinition> | AnyArray<SchemaTypeOptions<ObjectId, EnforcedDocType>> :
T extends object[] ? (AnyArray<Schema<any, any, any>> | AnyArray<SchemaDefinition<Unpacked<T>>> | AnyArray<SchemaTypeOptions<Unpacked<T>, EnforcedDocType>>) :
T extends string[] ? AnyArray<StringSchemaDefinition> | AnyArray<SchemaTypeOptions<string, EnforcedDocType>> :
T extends number[] ? AnyArray<NumberSchemaDefinition> | AnyArray<SchemaTypeOptions<number, EnforcedDocType>> :
T extends boolean[] ? AnyArray<BooleanSchemaDefinition> | AnyArray<SchemaTypeOptions<boolean, EnforcedDocType>> :
T extends Function[] ? AnyArray<Function | string> | AnyArray<SchemaTypeOptions<Unpacked<T>, EnforcedDocType>> :
T extends Types.ObjectId[] ? AnyArray<ObjectIdSchemaDefinition> | AnyArray<SchemaTypeOptions<ObjectId, EnforcedDocType, THydratedDocumentType>> :
T extends object[] ? (AnyArray<Schema<any, any, any>> | AnyArray<SchemaDefinition<Unpacked<T>>> | AnyArray<SchemaTypeOptions<Unpacked<T>, EnforcedDocType, THydratedDocumentType>>) :
T extends string[] ? AnyArray<StringSchemaDefinition> | AnyArray<SchemaTypeOptions<string, EnforcedDocType, THydratedDocumentType>> :
T extends number[] ? AnyArray<NumberSchemaDefinition> | AnyArray<SchemaTypeOptions<number, EnforcedDocType, THydratedDocumentType>> :
T extends boolean[] ? AnyArray<BooleanSchemaDefinition> | AnyArray<SchemaTypeOptions<boolean, EnforcedDocType, THydratedDocumentType>> :
T extends Function[] ? AnyArray<Function | string> | AnyArray<SchemaTypeOptions<Unpacked<T>, EnforcedDocType, THydratedDocumentType>> :
T | typeof SchemaType | Schema<any, any, any> | SchemaDefinition<T> | Function | AnyArray<Function>;

/** Defines a virtual with the given name that gets/sets this path. */
alias?: string | string[];

/** Function or object describing how to validate this schematype. See [validation docs](https://mongoosejs.com/docs/validation.html). */
validate?: SchemaValidator<T, EnforcedDocType> | AnyArray<SchemaValidator<T, EnforcedDocType>>;
validate?: SchemaValidator<T, EnforcedDocType, THydratedDocumentType> | AnyArray<SchemaValidator<T, EnforcedDocType, THydratedDocumentType>>;

/** Allows overriding casting logic for this individual path. If a string, the given string overwrites Mongoose's default cast error message. */
cast?: string |
Expand Down
7 changes: 6 additions & 1 deletion types/validation.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
declare module 'mongoose' {

type SchemaValidator<T, EnforcedDocType> = RegExp | [RegExp, string] | Function | [Function, string] | ValidateOpts<T, EnforcedDocType> | ValidateOpts<T, EnforcedDocType>[];
type SchemaValidator<T, EnforcedDocType, THydratedDocumentType> = RegExp
| [RegExp, string]
| Function
| [Function, string]
| ValidateOpts<T, THydratedDocumentType>
| ValidateOpts<T, THydratedDocumentType>[];

interface ValidatorProps {
path: string;
Expand Down