Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

types: correct this for validate.validator schematype option #14720

Merged
merged 2 commits into from
Jul 4, 2024

Conversation

vkarpov15
Copy link
Collaborator

Fix #14696

Summary

Ensure this has the correct type in validate.validator below.

    isActive: {
      type: Boolean,
      default: false,
      validate: {
        validator(v: any) {
          expectAssignable<User>(this);
          return !v || this.name === 'super admin';
        }
      }
    }

I made 2 changes to support this:

  1. passing EnforcedDocType down to ValidateFn via ValidateOpts and SchemaValidator
  2. Removing LegacyAsyncValidateFn. For some reason, LegacyAsyncValidateFn breaks these tests, and I have no idea why. It has something to do with the done function. Either way, LegacyAsyncValidateFn is no longer necessary because we removed support for validators that receive a callback in Mongoose 6, so I think it is safe to remove.

Examples

@vkarpov15 vkarpov15 added this to the 8.4.5 milestone Jul 2, 2024
@vkarpov15 vkarpov15 modified the milestones: 8.4.5, 8.4.6 Jul 3, 2024
@hasezoey hasezoey added the typescript Types or Types-test related issue / Pull Request label Jul 4, 2024
@vkarpov15 vkarpov15 merged commit 54561d0 into master Jul 4, 2024
5 checks passed
@vkarpov15 vkarpov15 deleted the vkarpov15/gh-14696 branch July 4, 2024 13:31
@pharapeti
Copy link

pharapeti commented Sep 24, 2024

For context: I'm upgrading from Mongoose v8.2.2 to v8.6.3

When performing a document create/update, this is the document (mongoose.Document).
When performing a MyModel.findOneAndUpdate query with options { runValidators: true }, this becomes is the query (mongoose.Query).

However, I believe due to these type changes make in this PR, Typescript seems to believe that this is always the document type - even in the case when it is a query.

Do you have any idea on how I can type the validator function so that Typescript knows that this is either a document OR a query type? @vkarpov15 @hasezoey


EDIT: After some experimentation, I managed to get the following somewhat working solution by specifying the type of this in the validator function.

type ValidatorThis = DocumentValidatorThis | QueryValidatorThis;
type DocumentValidatorThis = mongoose.Document & PassPersisted;
type QueryValidatorThis = mongoose.Query<PassRecord, PassPersisted>; // This is probably incorrect

endTime: {
  type: Date,
  required: true,
  validate: {
    validator: async function(this: ValidatorThis, endTime ): Promise<boolean> {
      if ('op' in this) {
        // Query validator
        const queryThis = this as QueryValidatorThis;
        let startTime: Date = this.get( 'pass.startTime' );

        ... can access query via `this`

        return endTime.getTime() > startTime.getTime();
      } else {
        // Document validator
        const documentThis = this as DocumentValidatorThis;
        return endTime.getTime() > documentThis.startTime.getTime();
      }
    },
    message: ( endTime ): string => `End time (${ endTime.value.toISOString() }) is before its start time`
  }
},

@vkarpov15
Copy link
Collaborator Author

@pharapeti you're right that the workaround is to explicitly set the type of this in the validator function. We don't currently have | Query in the fix in this PR, and adding it would be a breaking change. We're going to put in a PR to fix this issue and some related issues, but you'll likely have to use the workaround with explicit this typing for the near future.

@pharapeti
Copy link

@vkarpov15 Thanks for confirming that, will implement the workaround for now 👍

Cheers for the speedy reply 🙏

@vkarpov15 vkarpov15 restored the vkarpov15/gh-14696 branch November 5, 2024 16:45
@RadotJar
Copy link

RadotJar commented Feb 6, 2025

pharapeti's workaround no longer appears to work as of v8.9.7.

Using the same example provided, I get the following error on the type of 'this':

errorMongoose

It seems that the validator function is now expecting the 'this' argument to be of the 'PassPersisted' type, which I assume is the raw unhydrated data type representing what is stored in MongoDB. This does not align with my understanding of what is written in the docs at all.

@vkarpov15
Copy link
Collaborator Author

@RadotJar can you please open a new issue and follow the issue template?

@RadotJar
Copy link

RadotJar commented Feb 7, 2025

I have created one here: #15242

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
typescript Types or Types-test related issue / Pull Request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Validate in schema options is not properly typed
4 participants