Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Typescript + schema should type check for whether field is required or optional. #11158

Closed
tianhuil opened this issue Dec 30, 2021 · 3 comments
Closed
Labels
discussion If you have any thoughts or comments on this issue, please share them!

Comments

@tianhuil
Copy link

tianhuil commented Dec 30, 2021

Do you want to request a feature or report a bug?
Request a feature

What is the current behavior?
Consider the following example:

interface User {
  name: string;
  email: string;
  avatar?: string;
}

const schema = new Schema<User>({
  name: { type: String, required: true },
  email: { type: String, required: true },
  avatar: String
});

In the above, if avatar were required in the interface, the schema's non-required avatar would not throw a compile time error. Similarly, if name were optional in the interface, no error is reported from the schema's name being required. This appears to be expected (see docs):

You as the developer are responsible for ensuring that your document interface lines up with your Mongoose schema. For example, Mongoose won't report an error if email is required in your Mongoose schema but optional in your document interface.

What is the expected behavior?
I would like for the schema to type-check whether a field is required based on the interface. This is possible using typescript's typing system (e.g. Stackoverflow):

type MappedC<A, B> = {
  [K in keyof A & keyof B]:
  A[K] extends B[K]
    ? never
    : K
};

type OptionalKeys<T> = MappedC<T, Required<T>>[keyof T];

If there is interest, I'm happy to contribute a PR.

What are the versions of Node.js, Mongoose and MongoDB you are using? Note that "latest" is not a version.
This appears to be true for all versions of Mongoose and MongoDB.

@IslandRhythms IslandRhythms added the new feature This change adds new functionality, like a new method or class label Dec 30, 2021
@DavideViolante
Copy link
Contributor

I think duplicate of #9715

@vkarpov15
Copy link
Collaborator

@tianhuil I'm not sure that would be entirely correct. For example, you could do:

interface User {
  name: string;
  email: string;
  avatar: string;
}

const schema = new Schema<User>({
  name: { type: String, required: true },
  email: { type: String, required: true },
  avatar: String
});

schema.path('avatar').required(true); // Make `avatar` required

That's perfectly valid, even though avatar is not required in the original schema definition. The issue comes down to the fact that the schema definition doesn't necessarily represent the complete state of the schema.

Another example: you can also make all string fields required by default using mongoose.SchemaTypes.String.set('required', true);, which would mean all strings are required even though you don't set required in the schema definition.

@vkarpov15 vkarpov15 added discussion If you have any thoughts or comments on this issue, please share them! and removed new feature This change adds new functionality, like a new method or class labels Jan 5, 2022
@tianhuil
Copy link
Author

@vkarpov15: that's an interesting use case and not one that I would use.

Apparently the recommended solution is to use https://github.com/lstkz/ts-mongoose

Unfortunately, that project has not been updated since Nov. 2020.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discussion If you have any thoughts or comments on this issue, please share them!
Projects
None yet
Development

No branches or pull requests

4 participants