-
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
Changes from 11 commits
6574a07
6a14589
bc8f405
a4a299c
3cad633
7572e27
b5ebb10
9609db5
8787f77
a2cd086
daa0dd8
c440b0a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -280,8 +280,7 @@ export abstract class AbstractCursor< | |
return done(undefined, true); | ||
} | ||
|
||
next<any>(this, true, (err, doc) => { | ||
// FIXME(NODE): | ||
next<TSchema>(this, true, (err, doc) => { | ||
if (err) return done(err); | ||
|
||
if (doc) { | ||
|
@@ -296,9 +295,9 @@ export abstract class AbstractCursor< | |
} | ||
|
||
/** Get the next available document from the cursor, returns null if no more documents are available. */ | ||
next<T = TSchema>(): Promise<T | null>; | ||
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; | ||
next(callback?: Callback<TSchema | null>): Promise<TSchema | null> | void { | ||
return maybePromise(callback, done => { | ||
if (this[kId] === Long.ZERO) { | ||
return done(new MongoCursorExhaustedError()); | ||
|
@@ -311,9 +310,9 @@ export abstract class AbstractCursor< | |
/** | ||
* Try to get the next available document from the cursor or `null` if an empty batch is returned | ||
*/ | ||
tryNext<T = TSchema>(): Promise<T | null>; | ||
tryNext<T = TSchema>(callback: Callback<T | null>): void; | ||
tryNext<T = TSchema>(callback?: Callback<T | null>): Promise<T | null> | void { | ||
tryNext(): Promise<TSchema | null>; | ||
tryNext(callback: Callback<TSchema | null>): void; | ||
tryNext(callback?: Callback<TSchema | null>): Promise<TSchema | null> | void { | ||
return maybePromise(callback, done => { | ||
if (this[kId] === Long.ZERO) { | ||
return done(new MongoCursorExhaustedError()); | ||
|
@@ -329,10 +328,10 @@ export abstract class AbstractCursor< | |
* @param iterator - The iteration callback. | ||
* @param callback - The end callback. | ||
*/ | ||
forEach<T = TSchema>(iterator: (doc: T) => boolean | void): Promise<void>; | ||
forEach<T = TSchema>(iterator: (doc: T) => boolean | void, callback: Callback<void>): void; | ||
forEach<T = TSchema>( | ||
iterator: (doc: T) => boolean | void, | ||
forEach(iterator: (doc: TSchema) => boolean | void): Promise<void>; | ||
forEach(iterator: (doc: TSchema) => boolean | void, callback: Callback<void>): void; | ||
forEach( | ||
iterator: (doc: TSchema) => boolean | void, | ||
callback?: Callback<void> | ||
): Promise<void> | void { | ||
if (typeof iterator !== 'function') { | ||
|
@@ -341,7 +340,7 @@ export abstract class AbstractCursor< | |
return maybePromise(callback, done => { | ||
const transform = this[kTransform]; | ||
const fetchDocs = () => { | ||
next<T>(this, true, (err, doc) => { | ||
next<TSchema>(this, true, (err, doc) => { | ||
if (err || doc == null) return done(err); | ||
let result; | ||
// NOTE: no need to transform because `next` will do this automatically | ||
|
@@ -358,7 +357,7 @@ export abstract class AbstractCursor< | |
for (let i = 0; i < internalDocs.length; ++i) { | ||
try { | ||
result = iterator( | ||
(transform ? transform(internalDocs[i]) : internalDocs[i]) as T // TODO(NODE-3283): Improve transform typing | ||
(transform ? transform(internalDocs[i]) : internalDocs[i]) as TSchema // TODO(NODE-3283): Improve transform typing | ||
); | ||
} catch (error) { | ||
return done(error); | ||
|
@@ -402,15 +401,15 @@ export abstract class AbstractCursor< | |
* | ||
* @param callback - The result callback. | ||
*/ | ||
toArray<T = TSchema>(): Promise<T[]>; | ||
toArray<T = TSchema>(callback: Callback<T[]>): void; | ||
toArray<T = TSchema>(callback?: Callback<T[]>): Promise<T[]> | void { | ||
toArray(): Promise<TSchema[]>; | ||
toArray(callback: Callback<TSchema[]>): void; | ||
toArray(callback?: Callback<TSchema[]>): Promise<TSchema[]> | void { | ||
return maybePromise(callback, done => { | ||
const docs: T[] = []; | ||
const docs: TSchema[] = []; | ||
const transform = this[kTransform]; | ||
const fetchDocs = () => { | ||
// NOTE: if we add a `nextBatch` then we should use it here | ||
next<T>(this, true, (err, doc) => { | ||
next<TSchema>(this, true, (err, doc) => { | ||
if (err) return done(err); | ||
if (doc == null) return done(undefined, docs); | ||
|
||
|
@@ -420,7 +419,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 commentThe reason will be displayed to describe this comment to others. Learn more. can There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is the type of When you pass the transform into I suppose the most accurate would be There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
|
||
if (internalDocs) { | ||
docs.push(...internalDocs); | ||
|
@@ -458,11 +457,12 @@ export abstract class AbstractCursor< | |
* Map all documents using the provided function | ||
* If there is a transform set on the cursor, that will be called first and the result passed to | ||
* this function's transform. | ||
* @remarks | ||
* | ||
* **NOTE:** adding a transform changes the return type of the iteration of this cursor, it **does not** return | ||
* a new instance of a cursor. This means when calling map, you should always assign the result to a new | ||
* variable. Take note of the following example: | ||
* @remarks | ||
* **Note for Typescript Users:** adding a transform changes the return type of the iteration of this cursor, | ||
* it **does not** return a new instance of a cursor. This means when calling map, | ||
* you should always assign the result to a new variable in order to get a correctly typed cursor variable. | ||
* Take note of the following example: | ||
* | ||
* @example | ||
* ```typescript | ||
|
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 asT | 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!