Skip to content

Commit

Permalink
types(middleware): make this in document middleware the hydrated do…
Browse files Browse the repository at this point in the history
…c type, not raw doc type

Fix #15242
  • Loading branch information
vkarpov15 committed Feb 10, 2025
1 parent 1a2faa7 commit 6f316c0
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 23 deletions.
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);
}
28 changes: 14 additions & 14 deletions types/index.d.ts
Original file line number Diff line number Diff line change
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

0 comments on commit 6f316c0

Please sign in to comment.