0

I am using express and tsyringe for dependency injections.

When I try to use the service dependency on my controller I get an error UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'addressService' of undefined in file addressController.ts

I've searched for several videos and articles and I couldn't find a way to solve them. I will leave my code below

addressRepository.ts

import { AddressResponseDTO } from '../../dtos/response/address/addressResponseDTO';

export interface IAddressRepository {
  getAddresses(): Array<AddressResponseDTO>;
}

addressRepositoryImpl.ts

import { AddressResponseDTO } from '../../dtos/response/address/addressResponseDTO';
import { IAddressRepository } from '../declarations/addressRepository';

export default class AddressRepositoryImpl implements IAddressRepository {
  getAddresses(): Array<AddressResponseDTO> {
    const address1: AddressResponseDTO = {
      id: 'ADR123',
      postalCode: '17014273',
      address: 'Rua José Aiello',
      district: 'Centro',
      number: '347',
      city: 'Bauru',
      state: 'São Paulo',
      phoneNumber: '16997102842',
      clientName: 'João Mário Marcelo Campos',
    };

    const address2: AddressResponseDTO = {
      id: 'ADR456',
      postalCode: '07135290',
      address: 'Rua Mariano Moya Peramos',
      district: 'Jardim Adriana',
      number: '1103',
      city: 'Guarulhos',
      state: 'São Paulo',
      phoneNumber: '16997102842',
      clientName: 'João Mário Marcelo Campos',
    };

    return [address1, address2];
  }
}

addressService.ts

import { AddressResponseDTO } from '../../dtos/response/address/addressResponseDTO';
import ResultResponseDTO from '../../dtos/response/resultResponseDTO';

export interface IAddressService {
  getAddresses(): ResultResponseDTO<Array<AddressResponseDTO>>;
}

addressServiceImpl.ts

import { StatusCodes } from 'http-status-codes';
import { inject, injectable } from 'tsyringe';
import logger from '../../configurations/logger';
import { AddressResponseDTO } from '../../dtos/response/address/addressResponseDTO';
import ResultResponseDTO from '../../dtos/response/resultResponseDTO';
import { IAddressRepository } from '../../repositories/declarations/addressRepository';
import { IAddressService } from '../declarations/addressService';

@injectable()
export default class AddressServiceImpl implements IAddressService {
  private addressRepository: IAddressRepository;

  constructor(@inject('AddressRepository') addressRepository: IAddressRepository) {
    this.addressRepository = addressRepository;
  }

  getAddresses(): ResultResponseDTO<AddressResponseDTO[]> {
    try {
      logger.info('AddressService.getAddresses - start');

      const addresses = this.addressRepository.getAddresses();

      logger.info('AddressService.getAddresses - end');

      return ResultResponseDTO.ok(StatusCodes.OK, '', addresses);
    } catch (error) {
      logger.error(`AddressService.getAddresses - error - message ${error}`);
      return ResultResponseDTO.fail(
        StatusCodes.INTERNAL_SERVER_ERROR,
        'Error getting addresses',
        error,
      );
    }
  }
}

addressController.ts

Error at line: const result = this.addressService.getAddresses();

import { Request, Response } from 'express';
import { inject, injectable } from 'tsyringe';
import { IAddressService } from '../services/declarations/addressService';

@injectable()
export class AddressController {
  constructor(@inject('AddressService') private addressService: IAddressService) {}

  public async getAddresses(request: Request, response: Response): Promise<Response> {
    const result = this.addressService.getAddresses();
    return response.status(result.httpStatus).json(result.getResponse());
  }
}

routes.ts

import { Router } from 'express';
import { container } from 'tsyringe';
import { AddressController } from './controllers/addressController';
import AddressRepositoryImpl from './repositories/implementations/addressRepositoryImpl';
import AddressServiceImpl from './services/implementations/addressServiceImpl';

const routes = Router();

container
  .register('AddressRepository', {
    useClass: AddressRepositoryImpl,
  })
  .resolve(AddressRepositoryImpl);

container
  .register('AddressService', {
    useClass: AddressServiceImpl,
  })
  .resolve(AddressServiceImpl);

const addressController = container.resolve(AddressController);

routes.get('/', (request, response) => {
  response.send('It works!');
});

// AddressController
routes.route('/v1/address').get(addressController.getAddresses);

export default routes;

1 Answers1

0

You register service inside IoC as 'AddressServiceImpl' and after that try to call to it as 'AddressService'.

// service file
@injectable()
export default class AddressServiceImpl implements IAddressService {

...

// controller file

    @injectable()
    export class AddressController {
      constructor(@inject('AddressService') private addressService: IAddressService) {}