From c2cdb80f1b7d902d32456eab451a3255fbdfc2e0 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 2 Jul 2024 15:08:51 -0400 Subject: [PATCH] types: correct `this` for `validate.validator` schematype option Fix #14696 --- test/types/schema.test.ts | 46 ++++++++++++++++++++++++++++++++++++++- types/schematypes.d.ts | 2 +- types/validation.d.ts | 21 +++++++----------- 3 files changed, 54 insertions(+), 15 deletions(-) diff --git a/test/types/schema.test.ts b/test/types/schema.test.ts index bbbcdd5d71f..9dab60d2022 100644 --- a/test/types/schema.test.ts +++ b/test/types/schema.test.ts @@ -18,7 +18,8 @@ import { SchemaType, Types, Query, - model + model, + ValidateOpts } from 'mongoose'; import { expectType, expectError, expectAssignable } from 'tsd'; import { ObtainDocumentPathType, ResolvePathType } from '../../types/inferschematype'; @@ -1511,3 +1512,46 @@ function gh13772() { const doc = new TestModel(); expectAssignable(doc.toObject()); } + +function gh14696() { + interface User { + name: string; + isActive: boolean; + isActiveAsync: boolean; + } + + const x: ValidateOpts = { + validator(v: any) { + expectAssignable(this); + return !v || this.name === 'super admin'; + } + }; + + const userSchema = new Schema({ + name: { + type: String, + required: [true, 'Name on card is required'] + }, + isActive: { + type: Boolean, + default: false, + validate: { + validator(v: any) { + expectAssignable(this); + return !v || this.name === 'super admin'; + } + } + }, + isActiveAsync: { + type: Boolean, + default: false, + validate: { + async validator(v: any) { + expectAssignable(this); + return !v || this.name === 'super admin'; + } + } + } + }); + +} diff --git a/types/schematypes.d.ts b/types/schematypes.d.ts index 778b83c7ad5..b7f1fc733b9 100644 --- a/types/schematypes.d.ts +++ b/types/schematypes.d.ts @@ -60,7 +60,7 @@ declare module 'mongoose' { alias?: string | string[]; /** Function or object describing how to validate this schematype. See [validation docs](https://mongoosejs.com/docs/validation.html). */ - validate?: SchemaValidator | AnyArray>; + validate?: SchemaValidator | AnyArray>; /** Allows overriding casting logic for this individual path. If a string, the given string overwrites Mongoose's default cast error message. */ cast?: string | diff --git a/types/validation.d.ts b/types/validation.d.ts index 488ead7e588..811d86f9262 100644 --- a/types/validation.d.ts +++ b/types/validation.d.ts @@ -1,6 +1,6 @@ declare module 'mongoose' { - type SchemaValidator = RegExp | [RegExp, string] | Function | [Function, string] | ValidateOpts | ValidateOpts[]; + type SchemaValidator = ValidateOpts; // RegExp | [RegExp, string] | Function | [Function, string] | ValidateOpts | ValidateOpts[]; interface ValidatorProps { path: string; @@ -13,23 +13,18 @@ declare module 'mongoose' { (props: ValidatorProps): string; } - interface ValidateFn { - (value: T, props?: ValidatorProps & Record): boolean; - } - - interface LegacyAsyncValidateFn { - (value: T, done: (result: boolean) => void): void; - } + type ValidateFn = + (this: EnforcedDocType, value: any, props?: ValidatorProps & Record) => boolean; - interface AsyncValidateFn { - (value: T, props?: ValidatorProps & Record): Promise; - } + type AsyncValidateFn = + (this: EnforcedDocType, value: any, props?: ValidatorProps & Record) => Promise; - interface ValidateOpts { + interface ValidateOpts { msg?: string; message?: string | ValidatorMessageFn; type?: string; - validator: ValidateFn | LegacyAsyncValidateFn | AsyncValidateFn; + validator: ValidateFn + | AsyncValidateFn; propsParameter?: boolean; } }