Home > Mobile >  TypeError: Cannot read properties of undefined (reading 'questionRecord') - questionRecord
TypeError: Cannot read properties of undefined (reading 'questionRecord') - questionRecord

Time:01-04

I am trying to record a question on a prisma model. The model is defined as following:

model QuestionRecord {
 id                    String                  @id
 institution           String
 title                 String
 imagepath             String
 alternatives          String
 subject               String
 topic                 String
 year                  Int
 StudentQuestionRecord StudentQuestionRecord[]
}

To make any record on that model, I use the following class and its typing:

import { randomUUID } from "crypto";

export interface QuestionEntity {
   id: string,
   year: number,
   title: string,
   topic: string,
   subject: string,
   imagepath: string,
   institution: string,
   alternatives: string,
};

export class Question {
   public _id: string;
   public props: Omit<QuestionEntity, 'id'>;


   constructor(props: Omit<QuestionEntity, 'id'>, id?: string) {
       
       this._id = id ?? randomUUID();
       this.props = props;
   }

   public get id() {
       return this._id;
   }

   public get title() {
       return this.props.title;
   }

   public set title(newQuestionTitle) {
       this.props.title = newQuestionTitle;
   }

   public get topic() {
       return this.props.topic;
   }

   public set topic(newQuestionTopic) {
       this.props.topic = newQuestionTopic;
   }

   public get subject() {
       return this.props.subject;
   }

   public set subject(newQuestionSubject) {
       this.props.subject = newQuestionSubject;
   }

   public get year() {
       return this.props.year;
   }

   public set year(newYear) {
       this.props.year = newYear
   }

   public get institution() {
       return this.props.institution;
   }

   public set institution(newInstitution) {
       this.props.institution = newInstitution;
   }

   public get alternatives() {
       return this.props.alternatives;
   }

   public set alternatives(newAlternatives) {
       this.props.alternatives = newAlternatives;
   }

   public get imagepath() {
       return this.props.imagepath;
   }

   public set imagepath(newImage) {
       this.props.imagepath = newImage;
   }
}

Finally, I have this route that allows one to request the creation of a question:

@Post('create/question')
 async createQuestionView(@Body() body: CreateQuestionBody) {
   const {id, year, title, topic, subject, imagepath, institution, alternatives } = body;

   const { question } = await this.createQuestion.execute({
     id,
     year,
     title,
     topic, 
     subject,
     imagepath,
     institution,
     alternatives 
   });
   return {question: QuestionViewModel.toHTTP(question)};
 }

By the way, here's other snippets that may be helpful in the troubleshooting, as suggested by Shea. Here is how execute method was written:

interface CreateQuestionResponse {
   question: Question;
}

@Injectable()
export class CreateQuestion {
   constructor(private questionRepository: QuestionRepository) {}

   async execute(request: QuestionEntity): Promise<CreateQuestionResponse> {
       const {
           institution, subject, topic, title,
           year, alternatives, imagepath
       } = request;

       const question = new Question({
           alternatives, 
           institution, 
           imagepath,
           subject, 
           topic, 
           title,
           year, 
   });

       await this.questionRepository.create(question)

       return { question };
   }
}

Here is how PrismaQuestionRepository was written:

export class PrismaQuestionRepository implements QuestionRepository {
   constructor(private prisma: PrismaService) {}

   async create(question: QuestionEntity): Promise<void> {
       const raw = PrismaQuestionMappper.toPrisma(question);

       await this.prisma.questionRecord.create({
           data: raw,
       })
   }
   async findQuestionById(questionId: string): Promise<QuestionEntity | null> {
       const question = await this.prisma.questionRecord.findUnique({
           where: {
               id: questionId,
           }
       });

       if (!question) return null;

       return PrismaQuestionMappper.toDomain(question);
   }
   async findQuestionsByYear(year: number): Promise<QuestionEntity[] | null> {
       const questions = await this.prisma.questionRecord.findMany({
           where: {
               year: year,
           }
       });

       if (!questions) return null;

       return questions.map(PrismaQuestionMappper.toDomain);
   }
   async findQuestionsByTitle(title: string): Promise<QuestionEntity[] | null> {
       const questions = await this.prisma.questionRecord.findMany({
           where: {
               title: title,
           }
       });

       if (!questions) return null;

       return questions.map(PrismaQuestionMappper.toDomain);
   }
   async findQuestionsByTopic(topic: string): Promise<QuestionEntity[] | null> {
       const questions = await this.prisma.questionRecord.findMany({
           where: {
               topic: topic,
           }
       });

       if (!questions) return null;

       return questions.map(PrismaQuestionMappper.toDomain);
   }
   async findQuestionsBySubject(subject: string): Promise<QuestionEntity[] | null> {
       const questions = await this.prisma.questionRecord.findMany({
           where: {
               subject: subject,
           }
       });

       if (!questions) return null;

       return questions.map(PrismaQuestionMappper.toDomain);
   }
   async findQuestionsByInstitution(institution: string): Promise<QuestionEntity[] | null> {
       const questions = await this.prisma.questionRecord.findMany({
           where: {
               institution: institution,
           }
       });

       if (!questions) return null;

       return questions.map(PrismaQuestionMappper.toDomain);
   }
   async findQuestionsBySubjectAndTopic(subject: string, topic: string): Promise<QuestionEntity[] | null> {
       const questions = await this.prisma.questionRecord.findMany({
           where: {
               subject: subject,
               topic: topic,
           }
       });

       if (!questions) return null;

       return questions.map(PrismaQuestionMappper.toDomain);
   }   
}

Here is how mapper was written:

export class PrismaQuestionMappper {
   static toPrisma(question: QuestionEntity) {
       return {
           id: question.id,
           year: question.year,
           title: question.title,
           topic: question.topic,
           subject: question.subject,
           imagepath: question.imagepath,
           institution: question.institution,
           alternatives: question.alternatives,
       };
   };

   static toDomain(raw: QuestionEntity) {
       return new Question({
           year: raw.year,
           title: raw.title,
           topic: raw.topic,
           subject: raw.subject,
           imagepath: raw.imagepath,
           institution: raw.institution,
           alternatives: raw.alternatives,
       });
   };
};

My application runs quite well, until I try to record a question. Whenever I try to, passing in all necessary fields, I got this error:

[Nest] 13784  - 03/01/2023, 09:00:47   ERROR [ExceptionsHandler] Cannot read properties of undefined (reading 'questionRecord')
TypeError: Cannot read properties of undefined (reading 'questionRecord')
   at PrismaQuestionRepository.create (/home/famialiaaes/Documents/Estudos/NestJs/student-microservice/student/src/infra/database/prisma/repositories/prisma.question.repository.ts:12:27)
   at CreateQuestion.execute (/home/famialiaaes/Documents/Estudos/NestJs/student-microservice/student/src/app/use-cases/question/create.question.ts:29:39)
   at AppController.createQuestionView (/home/famialiaaes/Documents/Estudos/NestJs/student-microservice/student/src/infra/http/controllers/app.controller.ts:52:52)
   at /home/famialiaaes/Documents/Estudos/NestJs/student-microservice/student/node_modules/@nestjs/core/router/router-execution-context.js:38:29
   at processTicksAndRejections (node:internal/process/task_queues:95:5)
   at /home/famialiaaes/Documents/Estudos/NestJs/student-microservice/student/node_modules/@nestjs/core/router/router-execution-context.js:46:28
   at /home/famialiaaes/Documents/Estudos/NestJs/student-microservice/student/node_modules/@nestjs/core/router/router-proxy.js:9:17

I know that this error occurs when a supposed property of an undefined thing is called. So I re-read all my code and refactor it in some snippets, as well I pocked around with it in order to see what can have been evaluated as undefined but could not dilute the problem yet. I hope someone can help me out with, pointing out some nuance that failed to see. Thanks in advance!

Issue solved: as PrismaQuestionRepository is a class that is part of the nestjs module, on top of it I should have put an @Injectable decorator, what I haven't since now. After doing this, the problem disappeared.

CodePudding user response:

It looks like this.prisma is undefined when you attempt to run this.prisma.questionRecord.create. When you instantiate PrismaQuestionRepository, you have to pass in prisma (looking at its constructor.) Make sure you are properly instantiating PrismaQuestionRepository, which seems to be the root of your error.

  • Related