2
votes

I am writing a node.js application using typescript and mongoose. I am using the typescript model approach and continue to receive "cannot read property CasterConstructor' of undefined" when I call the create method to create a new subdocument. An example of the code is outlined below:

seat.ts:
export let SeatSchema: Schema = new Schema({
    travelerId: {type: Schema.Types.ObjectId, required: true},
    seatClass: {type: Schema.Types.String, minlength: 5, maxlength:10, required: true, enum: [“FirstClass”, “Coach”]},
    row: {type: Schema.Types.Number, required: true},
    section: {type: Schema.Types.Number, required: true},
    hasBoarded: {type: Schema.Types.Boolean, required: false}
});


plane.ts:
export let PlaneSchema: Schema = new Schema({
    manufacturer: {type: Schema.Types.String, required: true},
    seatsChart: [SeatSchema],
    routeId: [{type: Schema.Types.ObjectId, ref: ‘routes’, required: true}];

iseat.ts: 
export interface ISeat {
    travelerId: string,
    seatClass: string,
    row: number,
    section: number,
    hasBoarded: boolean
}


iplane.ts:
export interface IPlane {
    manufacturer: string,
    seatsChart: Types.DocumentArray<ISeatModel>,
    routeId: [string]
}

iseatmodel.ts:
export interface ISeatModel extends ISeat, Subdocument {
}

iplanemodel.ts:
export interface IPlaneModel extends IPlane, Document {
}

planerepository.ts:
constructor(db) {
    this._model: Model<IPlaneModel> = db.model<IPlaneModel>(“Plane”, PlaneSchema);
}
.
.
.
addNewSeat(planeId: string, seat: ISeat) {
    let plane: IPlaneModel = await this._model.findById(planeId);
    let newSeat: ISeatModel = plane.SeatsChart.create(seatAttributes);
    plane.seatsChart.push(newSeat);
    let planeUpdated: IPlane = await plane.save();
}

This is the error I keep receiving: TypeError: Cannot read property 'casterConstructor' of undefined at Array.create (/node_modules/mongoose/lib/types/documentarray.js:236:35) . . . . .

I am not seeing what I could be missing. Could someone please review and let me know what I could be missing and if this is the right approach altogether.

Update: After I switched to using push, the problem seems to be in /mongoose/lib/types/array.js, _checkManualPopulation:

function _checkManualPopulation(arr, docs) {
  var ref = arr._schema.caster.options && arr._schema.caster.options.ref;
  if (arr.length === 0 &&
      docs.length > 0) {
    if (_isAllSubdocs(docs, ref)) {
      arr._parent.populated(arr._path, [], { model: docs[0].constructor });
    }
  }
}

For some reason, the _schema object is undefined when push gets called which results in the exception. I am not sure if this is a bug or if something else is not getting called that would otherwise initialize the _schema property?

2
have you looked here? github.com/Automattic/mongoose/issues/5648user9190555
No. I did not see this article, but I am currently using "import mongoose = require("mongoose");" instead of "import * as mongoose from 'mongoose'". Now, there is a place where I am using "import mongoose = require('mongoose')". Would that make a difference?user1790300

2 Answers

0
votes

I am not sure what you are doing when adding the subdocument? You should just add it as a POJO.

The following code has been tested and it works fine.

async function addNewSeat(planeId: string, seat: ISeat) {
  let plane = await PlaneModel.findById(planeId);
  plane.seatChart.push(seat);
  await plane.save();
}

Then call it like the following:

let plane = await PlaneModel.create({flightNumber:"AR44"});
await addNewSeat(plane.id, {
     travelerId:"x", 
     seatClass:"business", 
     row:4, 
     section:9, 
     hasBoarded:true
});
await addNewSeat(plane.id, {
     travelerId:"y", 
     seatClass:"economy", 
     row:42, 
     section:1, 
     hasBoarded:true
});
0
votes

I found the answer. I ended up having to move logic that creates the database connection from a separate library to an inversify.config.js file in the main project and inject the mongoose connection into each repository. That seems to have fixed the problem.