【问题标题】:Typescript extend module (augmentation)打字稿扩展模块(增强)
【发布时间】:2019-06-20 17:07:50
【问题描述】:

我想用我自己的类和函数来扩展已安装的模块(Mongoose)。 我编写了函数和类,它们工作正常。

现在我想将它们添加到mongoose 模块。 所以我现在拥有的是这个文件: mongoInstance.ts

import * as mg from 'mongoose'

class _Schema extends mg.Schema {
    constructor(definition?: mg.SchemaDefinition, options?: mg.SchemaOptions) {
        super(definition, options)
        this.addData()
    }
    private addData() {
        //do stuff
    }
}  

function _limitedRequest(schema: mg.Schema, options = 200) {
    schema.pre("find", function (next) {
        this.limit(options)
        next()
    })
}

declare module 'mongoose' {
    export class _Schema extends Schema {
        constructor(definition?: SchemaDefinition, options?: SchemaOptions)
        private addData(): void
    }
    export function _limitedRequest(schema: Schema, options?: number): void
}

现在我可以在我的应用程序的任何地方做:

otherFile.ts

import * as mg from 'mongoose'
//doesnt work
var test1= new mg._Schema({})
//works
var test2= new mg.Schema({})

所以 VSCode 向我推荐了我的课程,而 IntellIsense 有效。但似乎没有该类的实现。 将我的代码编译为 bundle.js 时,Webpack 不会抛出任何错误,但是当我尝试使用 node bundle.js 运行我的 bundle.js 时,它会显示:TypeError: mg._Schema is not a constructor p>

【问题讨论】:

    标签: node.js typescript mongoose


    【解决方案1】:

    在 mongoInstance.ts 中这样导入:

    import mongoose from "mongoose";
    

    在 mongoInstance.ts 中导出类

    export class _Schema extends mg.Schema { ...
    

    在你的 otherFile.ts 中

    import { _Schema} from "./otherFile";
    

    【讨论】:

    • 嘿,谢谢你的遮阳篷。但这不起作用。我不能只导入猫鼬,因为猫鼬没有默认导出。如果我将导入语句添加到 otherFile.ts 也不会更改错误消息。 (而且我不想显式导入我的 _Schema,我认为这适用于 Mongoose 模块扩充
    • 像这样导入猫鼬应该可以。如果要在 otherFile.ts 中导入它,请确保在 mongoInstance.ts 中导出该类。我建议不要修补现有模块,因为其他开发人员很难理解你在做什么。
    • 好的,我明白了。但是当我只是导出我的函数和 _Schema 类时,我经常会发现自己导入了 mongoose 和模式,这意味着当复杂性增加时会出现许多导入语句。有没有办法在不显式导入 _Schema 的情况下做到这一点?
    【解决方案2】:

    你需要两件事:

    1. 声明文件扩展mongoose的类型定义。
    2. 添加功能,使模块符合其新定义。

    mongoose.d.ts

    创建一个声明文件 (*.d.ts) 并将其包含在您的项目中。

    import * as mg from 'mongoose';
    
    declare module 'mongoose' {
      export class _Schema extends mg.Schema {
        constructor(definition?: mg.SchemaDefinition, options?: mg.SchemaOptions);
      }
    
      export function _limitedRequest(schema: mg.Schema, options: number): void;
    }
    

    mongoose-instance.ts

    添加您刚刚声明的功能。

    import mg from 'mongoose';
    
    mg._Schema = class extends mg.Schema {
        constructor(definition?: mg.SchemaDefinition, options?: mg.SchemaOptions) {
            super(definition, options)
            this.addData()
        }
        private addData() {
            //do stuff
        }
    }
    
    mg._limitedRequest = function _limitedRequest(schema: mg.Schema, options = 200) {
      schema.pre("find", function (next) {
          this.limit(options)
          next()
      })
    }
    
    export default mg;
    

    consumer.ts

    从现在开始,使用您的本地版本的mongoose

    import mongoose from '../path/to/mongoose-instance';
    
    console.log(mongoose._Schema);
    

    如果您遇到与默认导入相关的任何问题,请确保在您的 tsconfig.json 中启用这两个标志:allowSyntheticDefaultImportsesModuleInterop

    【讨论】:

    • 是的,这段代码有效。问题是mg._Schema= class extends Schema 给了我警告,因为_Schema 不是猫鼬的属性
    • 这意味着我的答案的第一部分没有正确实现——它的作用是告诉 TypeScript Schema 是 mongoose 的属性。您确定 mongoose.d.ts 包含在您的项目中吗?请在您的tsconfig.json 中查看files/include/exclude
    • 现在我在 mongoInstance.ts 中做了declare module "mongoose"。所以它有效。但是当我尝试分配 mg._Schema=class extends Schema 时它仍然给出一个错误它说我不能分配它,因为它是一个只读值。
    • 您导入为import mg from 'mongoose' 还是import * as mg from 'mongoose';?它只能与第一种方法一起使用。
    • 我修改了代码以在没有默认导入/导出的情况下工作。所以在 mongoInstance.ts 我做export {mg}
    猜你喜欢
    • 2016-07-04
    • 2016-12-12
    • 2018-02-11
    • 2021-09-25
    • 1970-01-01
    • 2019-01-20
    • 2020-05-19
    • 2021-12-26
    • 2019-09-18
    相关资源
    最近更新 更多