typescripthapi

`TypeError: Cannot read properties of undefined (reading `<typescript_attributes>')`


I'm a novice in typescript. I was received error like this:

TypeError: Cannot read properties of undefined (reading '_service')
  at ...
  at ...
  at ...

when trying to call getNotesHandler() function. This is a full code:

import { Request, ResponseObject, ResponseToolkit } from "@hapi/hapi";
import { ClientError } from "../../exceptions/ClientError";
import { NotesService } from "../../services/inMemory/NotesService";
import { notesValidator, NotesValidator } from "../../validator/notes";

export class NotesHandler {
  _service: NotesService = new NotesService();
  _validator: NotesValidator;
  
  constructor(service: NotesService, validator: NotesValidator) {
    this._service = service;
    this._validator = validator;
    console.log('Service initialized', this._service)
    console.log('Validator initialized', this._validator)
  }

  postNoteHandler(request: Request, h: ResponseToolkit): ResponseObject {
    try {
      this._validator.validateNotePayload(request.payload);
      const data: NoteInput = JSON.parse(request.payload.toString());

      const noteId = this._service.addNote(data.title, data.body, data.tags);

      const response = h.response({
        status: 'success',
        message: `Note with id ${noteId} was added`,
        data: {
          noteId,
        }
      });

      response.code(201);
      return response;
    } catch(error) {
      if (error instanceof ClientError) {
        const response = h.response({
          status: 'error',
          message: error.message,
        });

        response.code(error.statusCode);
        return response;
      }

      // Server Error
      const response = h.response({
        status: 'error',
        message: 'Internal server error',
      });
      response.code(500);
      console.error(error);
      return response;
    }
  }

  getNotesHandler(request: Request, h: ResponseToolkit): ResponseObject {
    console.log("getNotesHandler");
    const notes = this._service.getNotes();
    const response = h.response({
      status: 'success',
      message: 'Notes were retrieved',
      data: notes,
    });
    response.code(200);
    return response;
  }

  getNoteByIdHandler(request: Request, h: ResponseToolkit): ResponseObject {
    try {
      const noteId = request.params.id;
      const note = this._service.getNoteById(noteId);
      const response = h.response({
        status: 'success',
        data: {
          note,
        }
      });
      response.code(200);
      return response;
    } catch(error) {
      if (error instanceof ClientError) {
        const response = h.response({
          status: 'error',
          message: error.message,
        });

        response.code(error.statusCode);
        return response;
      }

      // Server Error
      const response = h.response({
        status: 'error',
        message: 'Internal server error',
      });
      response.code(500);
      console.error(error);
      return response;
    }
  }

  putNoteByHandler(request: Request, h: ResponseToolkit): ResponseObject {
    try {
      this._validator.validateNotePayload(request.payload);
      const noteId = request.params.id;

      this._service.editNoteById(
        noteId, JSON.parse(request.payload.toString())
      );

      const response = h.response({
        status: 'success',
        message: `Note with id ${noteId} was edited`,
      });
      return response;
    } catch(error) {
      if (error instanceof ClientError) {
        const response = h.response({
          status: 'fail',
          message: error.message,
        });
        response.code(error.statusCode);
        return response;
      }
 
      // Server ERROR!
      const response = h.response({
        status: 'error',
        message: 'Server goes error.',
      });
      response.code(500);
      console.error(error);
      return response;
    }
  }

  deleteNoteByIdHandler(request: Request, h: ResponseToolkit): ResponseObject {
    try {
      const noteId = request.params.id;
      this._service.deleteNoteById(noteId);
      const response = h.response({
        status: 'success',
        message: `Note with id ${noteId} was deleted`,
      });
      return response;
    } catch(error) {
      if (error instanceof ClientError) {
        const response = h.response({
          status: 'fail',
          message: error.message,
        });
        response.code(error.statusCode);
        return response;
      }
 
      // Server ERROR!
      const response = h.response({
        status: 'error',
        message: 'Server goes error.',
      });
      response.code(500);
      console.error(error);
      return response;
    }
  }

I also tried to console.log(this._service) in constructor() if the value is undefined or not. But unfortunately there isn't. It gives output in my console:

Service initialized NotesService { _notes: [] }
Validator initialized { validateNotePayload: [Function: validateNotePayload] }

Still confused why _service is undefined when it calls in getAllNotes(). The same issue was occured for _validator attributes and happen in another function/attributes in NotesHandler class. Thanks in advance


Solution

  • The error doesn't say anything about _service being undefined.

    It says that you are trying to do undefined._service so this must be undefined.

    You probably lost this context while passing getNotesHandler somewhere. Try using bind.

    Also, it's not related to TypeScript as TypeScript doesn't exist at runtime. It's stricte JavaScript error.