打字稿与实现接口一起扩展类

Posted

技术标签:

【中文标题】打字稿与实现接口一起扩展类【英文标题】:typescript extends class along with implement interface 【发布时间】:2020-12-25 22:13:36 【问题描述】:

我正在尝试扩展第三方库类 mongooseJs,以便我可以在其中拥有一些自定义功能。我过去用 javascript 做过这个,像这样

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)

但是,当我尝试在 typescript 中做类似的事情时,如下所示,它给了我一个错误

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

此代码

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

我想要做的是提供我自己的接口CustomMongooseBase,这反过来又扩展了Mongoose 接口。我希望我的新班级 CustomMongoose 的调用者拥有我的新功能和其他所有内容。所以在具体实现中,我扩展了mongoose.Mongoose,它实现了Mongoose接口所需的所有方法,我的自定义类实现了我自己的接口所需的新方法myCustomMethod,所以这应该可以工作,但是不是。

我在这里做错了什么? (打字稿新手,所以想了解一下)

====略有不同的变化与不同的错误====

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

现在又出现了一个不同的错误

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

这些是我的 package.json 依赖项

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

【问题讨论】:

感谢@T.J.Crowder,感谢您的建议。是的,在我的实际代码中,我就是这样的。让我也纠正一下这个问题。 您的问题有const mongoose = require("mongoose"); 紧随其后的是import Schema, Model, Document, Mongoose from "mongoose"; 这真的很奇怪。通常你使用 either CommonJS (require) ESM (import)。你不要混合它们。 【参考方案1】:

我认为问题在于

    您同时拥有const mongoose = require("mongoose");import Schema, Model, Document, Mongoose from "mongoose";。这真的,真的很奇怪。通常你使用或者 CommonJS (require) ESM (import)。你不要混合它们。

    还有,

    您在interface CustomMongooseBase extends Mongoose 上使用Mongoose,但您在class CustomMongoose extends mongoose.Mongoose implements CustomMongooseBase 上使用mongoose.Mongoose。我怀疑mongoose.Mongoose 没有解析到相同的类型。

我会通过只使用一种形式的模块导入来解决它,并且在命名方面保持一致:

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');
    

也就是说,CustomMongooseBase 没有理由需要扩展 Mongoose,您可以删除该位:

interface CustomMongooseBase 
  myCustomMethod(): void;


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

【讨论】:

对,我确实认为第一点是一个问题,即导入和要求。但是,在这种非常特殊的情况下,如果没有它,我就无法让它发挥作用。如果我只导入,那么它指的是 @types 而不是实际的 MongooseJS 实现,因此没有给我具体的类来传递功能。正如我所说,我正在尝试添加一些功能,同时将其余的具体实现留给 mongooseJS。库中的具体类是 mongoose.Mongoose,如果你参考我的 javascript 示例的话。 另外,对于第二点,我实现 base 的原因是,我希望我的接口的用户能够将他们可以访问的所有方法作为一种类型来访问。 @SubhashDike - 结合 requireimport 是行不通的。您需要找出并解决您在使用import 时遇到的任何问题。我怀疑这会解决问题,但如果没有,听起来你的包导入有问题。通常,当您拥有一个包并为其键入信息时,该类型信息与包的导出相关联。您不会单独导入实现和类型信息。您只需导入实现。 我按照您的建议尝试了,即同时删除了 require 和 import,并且只使用 import 它仍然不起作用。我认为这个问题很好地局限于这个特定的库。在我的 package.json 中,我同时拥有 @types/mongoose mongoose,我认为问题在于,当我导入它时,它只引用 @types/mongoose,我想扩展一个类,它是来自 mongoose 包的具体实现而不是来自@types,但它只是从@types 中提取抽象类,并在那里给出错误。请参阅更新的问题以获取更新的示例 @SubhashDike - 我确信 Mongoose 的类型信息定义正确。我建议从package.json 中完全删除mongoose@types/mongoose,添加mongoose,然后添加@types/mongoose。做后者时,记住--save-dev(不是--save,也不是没有,与--save相同):npm i @types/mongoose --save-dev

以上是关于打字稿与实现接口一起扩展类的主要内容,如果未能解决你的问题,请参考以下文章

Angular 6打字稿与KotlinJs集成

如何扩展递归打字稿接口?

如何扩展“Window”打字稿界面

打字稿 - 强制值成为接口的属性

打字稿:使用特定的扩展接口来满足通用的“扩展”类型参数?

打字稿扩展了两个像类型一样的接口?