-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
fix(NODE-3468): remove generic overrides from find #2935
Conversation
86c3055
to
5fc0e60
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Regarding your question re: the .find
functionality: I personally would find it super helpful. Since the result of the .find
can actually vary significantly, it makes sense to be able to type the final output while making sure the filter follows the schema. Just my .02
next<T = TSchema>(callback: Callback<T | null>): void; | ||
next<T = TSchema>(callback?: Callback<T | null>): Promise<T | null> | void { | ||
next(): Promise<TSchema | null>; | ||
next(callback: Callback<TSchema | null>): void; |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Our next functions explicitly return null when the end of the cursor is reached. Our callback definition only lets the second are be potentially undefined, so the | null
is very technically necessary, if one is triple equals checking for null.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. The following is purely pedantry and feel free to ignore it, because I likely would if I were you lol.
For transparency, do think a helper type here would be useful? So instead of showing the | null it would be Promise<EndOfCursor<TSchema>>
where EndOfCursor is defined as T | null
? Again, super minute and what not. Marking this comment as resolved so it's out of mind lol. Thanks for answering my questions!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's true we have this repeated in a number of places, consolidating it to type would help us make sure we don't get one override different from the others, but I'll defer that to an enhancement effort down the line for now I want this PR to unblock the issue with the generics, but I do appreciate the suggestion! thanks!
@@ -413,7 +412,7 @@ export abstract class AbstractCursor< | |||
// these do need to be transformed since they are copying the rest of the batch | |||
const internalDocs = (transform | |||
? this[kDocuments].splice(0, this[kDocuments].length).map(transform) | |||
: this[kDocuments].splice(0, this[kDocuments].length)) as T[]; // TODO(NODE-3283): Improve transform typing | |||
: this[kDocuments].splice(0, this[kDocuments].length)) as TSchema[]; // TODO(NODE-3283): Improve transform typing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can this[kDocuments]
be typed as TSchema[]
? In the class definition itself so these as TSchema[]
hacks can be removed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is the type of this[kDocuments]
although you did make me think of a potential improvement (really just internally for us) but if we instead type this[kTransform]
to (doc: TSchema) => TSchema
then we don't need these casts.
When you pass the transform into .map()
it will be (doc: TSchema) => T
but map will return a new Cursor<T>
. Where T
is from the result type of the function passed to .map
. So the argument that goes into this[kTransform]
is the old schema and it returns the "current" one.
I suppose the most accurate would be this[kTransform]: (doc: unknown) => TSchema
but then we need equivalent casting/whatever to narrow unknown
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well my original comment was because I didn't see a type on kDocument and was thinking about ways to get rid of the as
because this[kDocuments].splice
should automatically return something with the type of <Type of<this[kDocuments]>>[]
so in this case if the source array was already typed, then this would automatically be TSchema[] so the typing here made me curious.
I actually played around a lot with prototyping a change to ktransform and others when thinking about ways to be able to type projections fully, and narrowing that down was like, a several hundred line TS object that existed only for being able to pass around the type accurately, and I think the unknown
above might run into the same situation? Although would you be able to use the Partial
keyword here for some help? I like the idea of the different typing, just wondering if the effort required to type that unknown is worth it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the lack of reply, been focused on getting this PR ready for fixing the user issues. I think accurately typing the transform is something we should look into, but it would only affect our internal TS code so at the moment we wouldn't need to prioritize it. but going forward more accuracy even if it requires TS helpers etc. could help catch any issues here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I need to review more of this, but I wanted to capture at least some feedback
614ec7a
to
195e3b8
Compare
195e3b8
to
f911afd
Compare
b75d242
to
8787f77
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work! 🚀
Removing the generics from
find*
andtoArray/next
will make the result type more logical in scenarios where there is not schema or the filter specified is an incorrect type.Removed the same behavior from listCollections
Added a generic to db.aggregate where it should have been
Q: do we want to do something better with specifying a projection in your options argument to
find*
right now you can only "fix" the result with the.project<>()
builder style, maybe we continue to accept generics on find*. but we no longer make itFilter<T>
, the filter still has to be based on the schema (Filter<TSchema>
) but the result can be changed to the specified type in the generic. thoughts?