0

I have the following module which I need to export in a way as to avoid the error of " OverwriteModelError: Cannot overwrite Task model once compiled".

I've seen many answers explain this but I can't get it to work. The last line is the issue (the export default models...

import { Schema, model, models } from 'mongoose';

export interface ITask {
    title: string;
    description: string;
}

const TaskSchema = new Schema<ITask>({ 
    title: {type: String},
    description: {type: String}
            
},{
    timestamps: true,
    versionKey: false
}) 

export default  models['Task']<ITask>  ||  model<ITask>('Task', TaskSchema); 

I added models['Task']<ITask> randomly because everything I tried doesn't seem to work

When I import that module and use it

const tasks = await Task.find();

It gives a typescript error which I don't understand: Each member of the union type... has signatures, but none of those signatures are compatible with each other


EDIT

At pages/api/tasks/[id].ts I have this

import { dbConnect, runMiddleware } from "@db/index";
import Task from "@model/Task";
dbConnect();
const SingleTask: NextApiHandler = async (req, res) => {
    const { method, body, query: {id} } = req;
    const morgan = Morgan("dev");
  
    switch (method) {
      case "GET":
        try {
          const task = await Task.findById(id);
....

At pages/api/tasks/index.ts I have this

import { dbConnect, runMiddleware } from "@db/index";
import Task from "@model/Task";
dbConnect();
const Tasks: NextApiHandler = async (req, res) => {
  const { method, body } = req;
  const morgan = Morgan("dev");

  switch (method) {
    case "GET":
      try {
        const tasks = await Task.find();
....

And the dbConnect method refers to this

import { connect, connection, ConnectionStates } from "mongoose";
interface ConnectionInterface {
  isConnected: ConnectionStates;
}
const conn: ConnectionInterface = {
  isConnected: 0,
};
export async function dbConnect() {
  if (conn.isConnected === 1) return;
  const db = await connect(process.env.MONGODB_URI);
  conn.isConnected = db.connections[0].readyState;
  console.log("Connected to database", db.connection.db.databaseName);
}
relidon
  • 2,142
  • 4
  • 21
  • 37
  • According to the [documentation](https://mongoosejs.com/docs/typescript.html), `export default model("Task", TaskSchema)` should do it – Phil Aug 31 '22 at 01:52
  • @Phil Yes but without the models I get the error I mentioned at the beginning. I basically need this https://github.com/vercel/next.js/blob/canary/examples/with-mongodb-mongoose/models/Pet.js#L59 and that you did is the thing after `||` but without the thing before, I get the error – relidon Aug 31 '22 at 02:09
  • That shouldn't happen unless you're defining the `Task` model in multiple places – Phil Aug 31 '22 at 02:13
  • Make sure when you import the model you use consistent filename casing. See [this answer](https://stackoverflow.com/a/34291140/283366) – Phil Aug 31 '22 at 02:23
  • @Phil I do have the same import copy pasted `import Task from "@model/Task";` – relidon Aug 31 '22 at 02:36

1 Answers1

0

As long as you're only creating the Task model in one place, you should really only need the following...

export default model<ITask>("Task", TaskSchema);

However if you want to check for existing Task models before compilation, use something like this

import { Model, Schema, model, models } from "mongoose";

// ...

const Task = models.Task as Model<ITask> ?? model<ITask>("Task", TaskSchema);
export default Task;
Phil
  • 157,677
  • 23
  • 242
  • 245
  • That fixes the issue. I've edited my post. Could the fact that I'm calling `dbConnect` at every api endpoint give me the error (I tried to explain it in edits)? – relidon Aug 31 '22 at 02:45
  • 1
    I doubt it. I'd be more on the lookout for different import paths like `"./model/Task"` or `@model/task` or `@model/Task.ts`, etc. – Phil Aug 31 '22 at 02:51