mongoose-paginate-v2
mongoose-paginate-v2 copied to clipboard
Complete Example and explanation of usage with typescript
Is your feature request related to a problem? Please describe. The typescript snipet provided on readme is confuse and I was no able to make it work properly
Describe the solution you'd like Have a clear, complete and explained example of typescript usage of type definition. Including the missing imports from the reademe page.
Also if possible please provide an example to integrate with Nest js. Many Thanks!
@nickchauhan I am using like this... this works... but has this type definition problem...
I define a Model like so:
import * as mongoose from 'mongoose';
import * as mongoosePaginate from 'mongoose-paginate-v2';
interface MyType {
name: string;
};
const schemaOptions = {
timestamps: true,
};
const schema = new mongoose.Schema(
{
name: { type: String, trim: true, required: true },
},
schemaOptions
);
schema.plugin(mongoosePaginate);
schema.set('toObject', {
getters: true,
virtuals: true,
});
schema.set('versionKey', false);
export default mongoose.model<MyType>('MyType', schema);
then I just need to cast it to any due the typescript complain about the model do not have the paginate
method
(this.myTypeCollection as any).paginate({});
@herbertpimentel Can you try as below?
import * as mongoose from 'mongoose';
import * as mongoosePaginate from 'mongoose-paginate-v2';
import { Document, PaginateModel } from "mongoose";
interface MyType {
name: string;
};
const schemaOptions = {
timestamps: true,
};
const schema = new mongoose.Schema(
{
name: { type: String, trim: true, required: true },
},
schemaOptions
);
schema.plugin(mongoosePaginate);
schema.set('toObject', {
getters: true,
virtuals: true,
});
schema.set('versionKey', false);
// declare a mongoose document based on a Typescript interface representing your schema
interface MyTpyeDocument extends Document, MyType {}
// create the paginated model
const model = mongoose.model<MyTpyeDocument, PaginateModel<MyTpyeDocument>>(
"MyType",
schema,
"mytype"
);
export default model;
after that, you can paginate
import model from './schema';
const query = {
name : 'test'
}
model.paginate(query, {limit: 5, page: 1}).then(result => {
console.log(result);
});
I hope it helps!
Hello @aravindnc
I have this issue too but a slight difference in my request is that I want to dynamically type the items in the docs
array.
I do not want to use the ModelType. I want to be able to be able to pass a generic type when I call paginate
which will become the type for the items in docs
.
I want to do this because in a paginate query, one can decide to deselect some fields (using select
) and would like to type the response to fit. Another case like populate
also exists.
Is there any way that I can do that? I will be glad to contribute if need be.
Thanks.
Looking at the code at paginate we can achieve this by
interface PaginateModel<T, TQueryHelpers = {}, TMethods = {}>
extends Model<T, TQueryHelpers, TMethods> {
paginate<O extends PaginateOptions = PaginateOptions, UserType = T>(
query?: FilterQuery<T>,
options?: O,
callback?: (
err: any,
result: PaginateResult<PaginateDocument<UserType, TMethods, O>>
) => void
): Promise<PaginateResult<PaginateDocument<UserType, TMethods, O>>>;
}
where we use default generic parameters so a user can use it like so
UserModel.paginate<PaginateOptions, TypeForDocsArrayItem>(...)
They use PaginateOptions
when they do not have any type to pass in, as in the example above. The benefit of this option is that the API of the paginate
function is kept consistent.
OR
we can use an overload so that the user can avoid passing in PaginationOptions
before TypeForDocsArrayItem
like so
interface PaginateModel<T, TQueryHelpers = {}, TMethods = {}>
extends Model<T, TQueryHelpers, TMethods> {
paginate<O extends PaginateOptions = PaginateOptions, UserType = T>(
query?: FilterQuery<T>,
options?: O,
callback?: (
err: any,
result: PaginateResult<PaginateDocument<UserType, TMethods, O>>
) => void
): Promise<PaginateResult<PaginateDocument<UserType, TMethods, O>>>;
}
// the overload
interface PaginateModel<T, TQueryHelpers = {}, TMethods = {}>
extends Model<T, TQueryHelpers, TMethods> {
paginate<UserType = T, O extends PaginateOptions = PaginateOptions>(
query?: FilterQuery<T>,
options?: O,
callback?: (
err: any,
result: PaginateResult<PaginateDocument<UserType, TMethods, O>>
) => void
): Promise<PaginateResult<PaginateDocument<UserType, TMethods, O>>>;
}
I'll be glad to know what you think. Thank you.
@herbertpimentel Can you try as below?
import * as mongoose from 'mongoose'; import * as mongoosePaginate from 'mongoose-paginate-v2'; import { Document, PaginateModel } from "mongoose"; interface MyType { name: string; }; const schemaOptions = { timestamps: true, }; const schema = new mongoose.Schema( { name: { type: String, trim: true, required: true }, }, schemaOptions ); schema.plugin(mongoosePaginate); schema.set('toObject', { getters: true, virtuals: true, }); schema.set('versionKey', false); // declare a mongoose document based on a Typescript interface representing your schema interface MyTpyeDocument extends Document, MyType {} // create the paginated model const model = mongoose.model<MyTpyeDocument, PaginateModel<MyTpyeDocument>>( "MyType", schema, "mytype" ); export default model;
after that, you can paginate
import model from './schema'; const query = { name : 'test' } model.paginate(query, {limit: 5, page: 1}).then(result => { console.log(result); });
I hope it helps!
I'm doing exactly this, however the docs
in the response to the Model.paginate
method are typed as HydratedDocument<T, TMethods, TVirtuals>[]
and not my model's interface. Any idea how I can solve that? Here's a snippet:
const { docs, nextPage } = await MyModel.paginate()
// docs here is not typed as the type of MyModel
I've also tried MyModel.paginate<MyModelType>()
Hello @tdsoundation Have you taken a look at this article - Set Custom Types for docs items in mongoose-paginate-v2