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] define or derive typings for Query.select() and Query.findX(filter, projection) args relative to the given schema #11437
Comments
made a bit of progress on trying to make this generic: export type QuerySelectOption = 0 | 1;
export type PopulateOption<T> = string & keyof T;
export type SelectFields<T> = {
[field in PopulateOption<T>]?: QuerySelectOption;
}
export type SelectUserFields = SelectFields<IUser>;
User
.findOne({ username: "some name" })
// manually define "as" but at least some typing is here now!
.select({} as SelectUserFields); unfortunately not able to get it working for the i can do it manually with template literal type but cant get it to repeat X times (X = number of fields) dynamically. nor can i figure out how to exclude an already selected field export type PopulateOptions<T> =
| `${PopulateOption<T>}`
| `${PopulateOption<T>} ${PopulateOption<T>}`
| `${PopulateOption<T>} ${PopulateOption<T>} ${PopulateOption<T>}`
| `${PopulateOption<T>} ${PopulateOption<T>} ${PopulateOption<T>} ${PopulateOption<T>}`;
// repeat fieldNumber of times?
// exclude already selected option? |
which typescript version was again introducing template literals? |
Having TypeScript support for But that's a great start. |
If you put any in there, it renders the whole typing thing basically useless. :/ |
It still would give Intellisense support for most of the use cases. An incremental approach would be to give users IntelliSense support, and allow them to enter whatever they want, that way the software is not perfect, but it's in a better state than it previously was (no types support at all). Maybe someday, when we've covered all the use cases (I doubt we'll get to that day), we can make the typings strict in a major version. What do you think? |
@AbdelrahmanHafez just to clarify i am only able to get it working for i am not an expert at TS at all. i have worked with JS for years but just started with TS a few months ago. at this point im just hacking my way through it with research and trial/error. there may be some TS wizards that could figure it out. so far my research suggests it isnt possible to do dynamically. the reason being that there are a near infinite number of combinations (growing as N fields increases). |
i think a good starting point for this is figuring out how to correctly introspect the document and derive only the "custom fields" (non with that as a basis i think we can at least get the select options object typing working internal to mongoose instead of the looking ahead i believe (but again, im no expert in TS) that it should be possible to introspect for "nested paths" (object fields) and recursively introspect subdocuments. |
i did come across this SO answer which could give a lead for generating nested path strings. |
That's fine. Knowing that it's in the realm of possibility is good enough.
Likewise, it's pretty nice.
@taxilian @ahmedelshenawy25 here's a problem you might be interested in. |
TS is just wonderful. i really regret not having started sooner. it has completely transformed my development experience. i will never go back to JS for anything more than quick hack scripts. i used to think JS + JSDocs was enough. and for a time it was a "TS-light" solution. but when i ran into needing to share / reuse the JSDocs i realized i was basically reinventing TS. the rest is history! |
For those reasons, mongoose suggests you don't follow the same pattern in the original post.
I agree that this might be tricky, as stated above: the goal is to improve support for types, not have a perfect state, so it should be fine to start with simple top-level-fields selection, and then we can work on improving it to handle more cases such as deeply nested paths, index operators and all the other cases that we can support. |
Can you give us your wisdom you mighty typescript wizards? |
ah great point man. its funny i remember seeing that when i first started using mongoose with TS a few months ago and it made no sense to me. now it finally does! man this is so much easier to work with. this is the general pattern im using now: // used for create (user provided input of the doc)
interface IUserInput {
username: string;
password: string;
}
// adds timestamp fields (maybe theres an easier way?)
interface IWithTimestamps {
createdAt: string;
updatedAt: string;
}
// additional fields (any extra fields not received from input)
interface IUser extends IUserInput, IWithTimestamps {
internalField: string;
}
type SelectUserFieldOptions = SelectFieldOptions<IUser>;
const UserSchema = new Schema<IUser>({ ... }, { timestamps: true });
const User = mongoose.model("User", UserSchema); |
Hey right on @vkarpov15! Thanks for the help with this guys. Great feature. |
Do you want to request a feature or report a bug?
What is the current behavior?
when using the projection argument of a
Query.findX(filter, projection)
or chaining theQuery.select(arg)
method i would like to have typing support.the current typing for both
projection
andselect
args isany
What is the expected behavior?
define the arg Type as the fields in my schema
What are the versions of Node.js, Mongoose and MongoDB you are using? Note that "latest" is not a version.
v17.3.1
^6.2.0
The text was updated successfully, but these errors were encountered: