mongo-cursor-pagination icon indicating copy to clipboard operation
mongo-cursor-pagination copied to clipboard

Types for Typescript

Open maxim2muchcoffee opened this issue 5 years ago • 4 comments

Hi guys! It's a good plugin to use with mongoose. The only thing I'm missing is support for TypeScript types. For example TypeScript doesn't know what is .paginate() in such expression: this.questionModel.paginate({})

maxim2muchcoffee avatar Dec 07 '18 08:12 maxim2muchcoffee

I agree. Being new to ts as well made it a bit of a challenge. But I did some stack overflow research and one of them led to this:

declare module 'mongoose' {
  export interface IPaginateOptions {
    query: Object;
    limit?: number;
    next?: string;
  }

  export interface PaginateResult<T> {
    results: Array<T>;
    next: string;
  }

  export interface IPaginateModel<T extends Document> extends Model<T> {
    paginate(options: IPaginateOptions): Promise<PaginateResult<T>>;
  }

  export function model<T extends Document>(
    name: string,
    schema?: Schema,
    collection?: string,
    skipInit?: boolean,
  ): IPaginateModel<T>;

  export function model<T extends Document, U extends IPaginateModel<T>>(
    name: string,
    schema?: Schema,
    collection?: string,
    skipInit?: boolean,
  ): U;
}

declare module "mongo-cursor-pagination" {
  import mongoose from 'mongoose';
  export function mongoosePlugin(schema: mongoose.Schema): void;
}

I don't think it's perfect though. Just something that got it working. I definitely would appreciate if any advanced TS folks can help to sort out the typedef for mongo-cursor-pagination. :)

limianwang avatar Dec 09 '18 07:12 limianwang

For any of you that are using Typegoose, I created the following:

import { Model, DocumentQuery } from "mongoose";
import { InstanceType } from "typegoose";

export interface IPaginateOptions {
    query?: Object;
    limit?: number;
    fields?: Object;
    paginatedField?: string;
    sortAscending?: Boolean;
    next?: string;
    previous?: string;
}

export interface IPaginateResult<T> {
    hasNext: boolean;
    hasPrevious: boolean;
    next?: string;
    previous?: string;
    results: T[];
}

export interface IPaginateModel<T> extends Model<InstanceType<T>> {
    paginate(options: IPaginateOptions): DocumentQuery<IPaginateResult<T>, InstanceType<T>>;
}

and export your typegoose model as follows:

export const UserModel = new User().getModelForClass(User) as IPaginateModel<InstanceType<User>> & User & typeof User;

Now you can use paginate() anywhere as you would find():

const query = {}; // The query that you would normally use
const users = await UserModel.paginate({ query: query, limit: 10, paginatedField: "email", sortAscending: true });

ExtraBB avatar Feb 07 '19 10:02 ExtraBB

Building on top of @ExtraBB's answer w/ Typegoose v7.2.0 and Mongoose 5.9.20 as of writing.

I created a BaseModelSchema class which has a static paginate() function to be inherited by other domain-specific schema.

import { plugin, defaultClasses, DocumentType } from '@typegoose/typegoose';
import { DocumentQuery } from 'mongoose';

const MongoCursorPagination = require('mongo-cursor-pagination');

@plugin(MongoCursorPagination.mongoosePlugin) // https://github.com/mixmaxhq/mongo-cursor-pagination#with-mongoose
export class BaseModelSchema extends defaultClasses.Base {
  get id(): string {
    return this._id.toHexString();
  }

  static paginate<T>(this: T, options: IPaginateOptions): DocumentQuery<IPaginateResult<T>, DocumentType<T>> {
    return (this as any).paginate(options);
  }
}

interface IPaginateOptions {
  query?: object;
  limit?: number;
  fields?: object;
  paginatedField?: string;
  sortAscending?: boolean;
  next?: string;
  previous?: string;
}

interface IPaginateResult<T> {
  hasNext: boolean;
  hasPrevious: boolean;
  next?: string;
  previous?: string;
  results: T[];
}

Then usage:

class UserModelSchema extends BaseModelSchema {
  // your custom props
}

const UserModel = getModelForClass(UserModelSchema);

const users = await UserModel.paginate({ query: query, limit: 10, paginatedField: "email", sortAscending: true });

cerinoligutom avatar Jun 24 '20 15:06 cerinoligutom

Almost 3 years still not TypeScript support , sad :(

atTheShikhar avatar Nov 07 '21 12:11 atTheShikhar