I'm rather new to typescript and node.js but I wanted to learn something and try something new with angular, node and express. I still try to find some good practices to split express project into a couple of smaller parts and somehow I got into a problem. I wanted to create an abstract Controller class and some subclasses which would be typical REST controllers backed by express.Router().
Here's the base class - Controller:
import express, {Router} from "express";
export abstract class Controller {
public router = express.Router();
public path: string;
protected constructor(path: string) {
this.path = path;
console.log('Calling initializeRoutes() from superclass');
this.initializeRoutes();
}
abstract initializeRoutes(): void;
}
And the subclass - it's just an example - UserController class:
import {Controller} from "./Controller";
import express from "express";
export class UserController extends Controller {
private users = [
{name: 'User1', password: 'password1'},
{name: 'User2', password: 'password2'},
{name: 'User3', password: 'password3'}
]
constructor(path: string) {
super(path);
console.log('Calling initializeRoutes() from subclass');
this.initializeRoutes();
}
initializeRoutes(): void {
// console.log(this.router);
console.log(this.getAllUsers);
console.log(this.createAPost);
// this.router.get(this.path, this.getAllUsers);
// this.router.post(this.path, this.createAPost);
}
getAllUsers = (request: express.Request, response: express.Response) => {
response.send(this.users);
}
createAPost = (request: express.Request, response: express.Response) => {
const user = request.body;
this.users.push(user);
response.send(user);
}
The main problem is I would like to call initializeRoutes() in the base class but when I do it express throws error that I can't use undefined callbacks in router. I did some debugging and found that when use initializeRoutes() in the base class callbacks from subclasses are undefined whilst when run from subclasses everything is ok:
[1] [nodemon] starting `ts-node server\server.ts`
[1] Calling initializeRoutes() from superclass
[1] undefined
[1] undefined
[1] Calling initializeRoutes() from subclass
[1] [Function (anonymous)]
[1] [Function (anonymous)]
Why is that? Am I doing something wrong or missing something? Thanks in advance
EDIT: I tried the suggested solution:
export class UserController extends Controller {
constructor(path: string) {
super(path);
this.getAllUsers = this.getAllUsers.bind(this);
this.createAPost = this.createAPost.bind(this);
console.log('Calling initializeRoutes() from subclass');
// this.initializeRoutes();
}
initializeRoutes(): void {
// console.log(this.router);
this.getAllUsers = this.getAllUsers.bind(this);
this.createAPost = this.createAPost.bind(this);
console.log(this.getAllUsers);
console.log(this.createAPost);
this.router.get(this.path, this.getAllUsers);
this.router.post(this.path, this.createAPost);
}
}
When I put it into initializeRoutes() I get:
[1] TypeError: Cannot read property 'bind' of undefined [1] at UserController.initializeRoutes (C:\Blazej\Projects\pasteur\server\controller\UserController.ts:19:41)
When I put it into the constructor I get:
[1] Error: Route.get() requires a callback function but got a [object Undefined]