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

Complete Example and explanation of usage with typescript #162

Open
herbertpimentel opened this issue Mar 22, 2022 · 7 comments
Open

Complete Example and explanation of usage with typescript #162

herbertpimentel opened this issue Mar 22, 2022 · 7 comments
Labels
enhancement New feature or request

Comments

@herbertpimentel
Copy link

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.

@nickchauhan
Copy link

Also if possible please provide an example to integrate with Nest js. Many Thanks!

@herbertpimentel
Copy link
Author

herbertpimentel commented Mar 23, 2022

@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({});

@nickchauhan
Copy link

nickchauhan commented Mar 24, 2022

@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!

@aravindnc aravindnc added the enhancement New feature or request label Jun 8, 2022
@orimdominic
Copy link
Contributor

orimdominic commented Sep 15, 2023

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.

@orimdominic
Copy link
Contributor

orimdominic commented Sep 15, 2023

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.

@tdsoundation
Copy link

tdsoundation commented Nov 27, 2023

@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>()

@orimdominic
Copy link
Contributor

Hello @tdsoundation Have you taken a look at this article - Set Custom Types for docs items in mongoose-paginate-v2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

5 participants