Заголовочные файлы для метода плагина Mongoose (с расширением.methods и.statics)

Я пытаюсь создать заголовочные файлы Typescript для сценария, расширяющего мою модель Mongoose, с помощью метода.plugin. Текущая подпись из заголовочных файлов Mongoose:

export class Schema {
   // ...
   plugin(plugin: (schema: Schema, options?: Object) => void, 
                   options?: Object): Schema;
   // ...
}

Немного актуального кода из Mongoose-lib:

/**
 * Registers a plugin for this schema.
 *
 * @param {Function} plugin callback
 * @param {Object} [opts]
 * @see plugins
 * @api public
 */

Schema.prototype.plugin = function (fn, opts) {
  fn(this, opts);
  return this;
};

Тогда моя собственная модель, расширяющая плагин;

import passportLocalMongoose = require('passport-local-mongoose')
// ...
var userSchema = new mongoose.Schema({
    email: String,
    password: String,
});
// ...
userSchema.plugin(passportLocalMongoose, {
    usernameField: "email",
    usernameLowerCase: true
});

Фрагмент из источника паспорт-местный мангуст:

module.exports = function(schema, options) {
   // ...   
   schema.methods.setPassword = function (password, cb) {
      // ...
   }

   schema.statics.authenticate = function() {
      // ...
   }
   // ...
}

Проблема возникает в моем главном app.js

   // ...

   userSchema.authenticate()                // <<< Typescript error, undefined

   //   OR

   userSchemaInstance.setPassword(pass, cb) // <<< Typescript error, undefined

Проблема в том, что.authenticate и т. Д. Были динамически добавлены через .methods и .statics...

Я не могу найти способ смоделировать это в файлах заголовка машинописного текста.

Я пробовал дженерики и прочее, но не могу (динамически) применить предоставленные плагины-методы обратно к исходной модели. Я тоже пробовал plugin возвращение родового T extends S & P (где S расширяет схему от первого аргумента и P = сам плагин). Неудачно:-(

Любые предложения или примеры, как решить эту проблему?

1 ответ

Решение

Объявить интерфейсы в passport-local-mongoose.d.ts файл:

declare module 'mongoose' {
    // methods
    export interface PassportLocalDocument extends Document {
        setPassword(pass: string, cb: (err: any) => void);
    }

    // statics
    export interface PassportLocalModel<T extends PassportLocalDocument> extends Model<T> {
        authenticate(username: string, password: string, cb: (err: any) => void);
    }

    // plugin options
    export interface PassportLocalOptions {
        usernameField?: string;
        usernameLowerCase?: boolean;
    }

    export interface PassportLocalSchema extends Schema {
        plugin(
            plugin: (schema: PassportLocalSchema, options?: PassportLocalOptions) => void,
            options?: PassportLocalOptions): Schema;
    }

    export function model<T extends PassportLocalDocument>(
        name: string,
        schema?: PassportLocalSchema,
        collection?: string,
        skipInit?: boolean): PassportLocalModel<T>;
}

declare module 'passport-local-mongoose' {
    import mongoose = require('mongoose');
    var _: (schema: mongoose.Schema, Options?: Object) => void;
    export = _;
}

Используйте это в своем app.ts:

import mongoose = require('mongoose');
import passportLocalMongoose = require('passport-local-mongoose');

interface UserDocument extends mongoose.PassportLocalDocument {
    email: string,
    password: string;
}

var userSchema = <mongoose.PassportLocalSchema>new mongoose.Schema({
    email: String,
    password: String
});

userSchema.plugin(passportLocalMongoose, {
    usernameField: 'email',
    usernameLowerCase: true
});

var User = mongoose.model<UserDocument>('User', userSchema);
User.authenticate(userName, pass, cb);

var user = new User();
user.setPassword(newPass, cb);
Другие вопросы по тегам