Search code examples
node.jstypescriptmysql2

node and typescript: property undefined when call route


I'm decided to create a project without any ORM, only using mysql2 package + node(typescript), but I'm having a hard time figuring out this problem below:

TypeError: Cannot read property 'userService' of undefined

This error appears when I tried to call the get route /api/user, but the service is being initialized on my controller class. I tested only the query and is returning everything as expected.

The main structure of my project will have a repository for database queries, a service for bussiness logic and a controller that will manage my routes.

user repository

import pool from './../config/db';

interface IUser {
    id: number,
    login: string,
    created_at: Date,
    updated_at: Date
}

class User {
    async getUsers (): Promise<Array<IUser>> {
        try {
            const [rows]: [Array<IUser>] = await pool.query('SELECT * FROM `clients`', []);
            return rows;
        } catch (err) {
            return err;
        }
    }
}

export default User;

UserService

import User from './../repository/user';

class UserService {
    private user;

    constructor () {
        this.user = new User();
    }

    getUsers () {
        return this.user.getUsers();
    }
}

export default UserService;

UserController

import UserService from '../services/user.service';
import express from 'express';

class UserController {
    public path = '/user';
    public router = express.Router();
    public userService;

    constructor () {
        this.userService = new UserService();
        this.initializeRoutes();
    }

    private initializeRoutes (): void {
        this.router.get(this.path, this.get);
    }

    get (req, res) {
        res.send(this.userService.getUsers());
    }
}

export default UserController;

And on my main file, I have this method that will call the routes:

  private routes (): void {
        const routes = [
            new UserController()
        ];

        routes.forEach((route) => {
            this.app.use('/api', route.router);
        });
    }

Solution

  • In UserController, the get class method function is invoked by the router. So you should bind get function to the class instance mapper, so to this like that:

      constructor() {
        this.userService = new UserService();
        this.get = this.get.bind(this); // here you bind the function
        this.initializeRoutes();
      }