简体   繁体   中英

typescript extends class along with implement interface

I am trying to extend a third party library class mongooseJs so that I can have some custom functionality in there. I have done this in the past with Javascript, like this

const mongoose = require("mongoose");
class CustomMongoose extends mongoose.Mongoose {
    myCustomMethod() {
        console.log('this is my custom method');
    }
}

const a = new CustomMongoose();
a.model("test"); //This method does get called on parent correctly (code wouldn't work until connection is setup but you get the point)

However when I try to do similar thing in typescript, as below, it gives me an error

Type 'CustomMongoose' is missing the following properties from type 'CustomMongooseBase': pluralize, connect, createConnection, disconnect, and 39 more.

for this code

const mongoose = require("mongoose");
import { Schema, Model, Document, Mongoose } from "mongoose";

interface CustomMongooseBase extends Mongoose {
  myCustomMethod(): void;
}

class CustomMongoose extends mongoose.Mongoose implements CustomMongooseBase {
    myCustomMethod(): void {
        console.log('this is my custom method');
    }
}

//this is what I would expect to work, if this compiles fine
// const a = new CustomMongoose();
// a.myCustomMethods(); // should work
// a.model("modelName") //should also work, though this is from the base

What I am trying to do is that providing my own interface CustomMongooseBase , which in turn extends the Mongoose interface. I want the caller of my new class CustomMongoose to have my new functionality and everything else as pass through. So in the concrete implementation, I have extended mongoose.Mongoose which has implementation of all the methods Mongoose interface requires, and my custom class has implementation of new method myCustomMethod that my own interface requires, so this should be working, but it's not.

What I am doing wrong here? (New to typescript so trying to get my head around)

==== Slightly different variation with different error ====

import { Mongoose } from "mongoose";

export interface CustomMongooseBase extends Mongoose //extending at the interface level so that consumers have the full signature of mine as well as parent interface
{ 
  myCustomMethod(): void;
}

class CustomMongoose extends Mongoose implements CustomMongooseBase {
  myCustomMethod(): void {
    console.log("this is my custom method");
  }
}

//this is what I would expect to work, if this compiles fine
// const a = new CustomMongoose();
// a.myCustomMethods(); // should work
// a.model("modelName") //should also work, though this is from the base

and here is a different error now

Non-abstract class 'CustomMongoose' does not implement inherited abstract member 'ConnectionBase' from class 'typeof import("mongoose")'.ts(2515)

These are my package.json dependencies

"dependencies": {
    "@types/mongoose": "^5.7.36",
    "@types/node": "^14.6.4",
    "mongoose": "^5.10.3"
  }

I think the problem is that

  1. You have both const mongoose = require("mongoose"); and import { Schema, Model, Document, Mongoose } from "mongoose"; . That's really, really odd. Normally you use either CommonJS ( require ) or ESM ( import ). You don't mix them.

    And,

  2. You're using Mongoose on interface CustomMongooseBase extends Mongoose but you're using mongoose.Mongoose on class CustomMongoose extends mongoose.Mongoose implements CustomMongooseBase . I suspect mongoose.Mongoose isn't resolving to the same type.

I'd fix it by using just one form of module import, and being consistent about naming:

import { Schema, Model, Document, Mongoose } from "mongoose";

interface CustomMongooseBase extends Mongoose {
  myCustomMethod(): void;
}

class CustomMongoose extends Mongoose implements CustomMongooseBase {
    myCustomMethod(): void {
        console.log('this is my custom method');
    }
}

That said, there's no reason that CustomMongooseBase needs to extend Mongoose , you could just remove that bit:

interface CustomMongooseBase {
  myCustomMethod(): void;
}

class CustomMongoose extends Mongoose implements CustomMongooseBase {
    myCustomMethod(): void {
        console.log('this is my custom method');
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM