0

I`m making a rest api with express.js + typescript + typeorm

I was thinking that I've got some problem with AppDataSource or something of this sort, but it's good.

Here is my controller class:

import { RequestWithBody } from '@utils/types/request.type'
import { Response } from 'express'
import { AppDataSource } from '../../data-source'
import { Type } from './type.entity'

class TypeController {
    private typeRepository = AppDataSource.getRepository(Type)

    async create(req: RequestWithBody<{ name: string }>, res: Response) {
        console.log('this', this)

        const { name } = req.body
        const type = this.typeRepository.create({
            name
        })

        const createdType = await this.typeRepository.save(type)
        return res.json(createdType)
    }
}

export default new TypeController()

Here is route:

import { Router } from 'express'
import typeController from './type.controller'

const router = Router()

router.post('/', typeController.create)

export default router

Unfortunatelly in the console.log in the create method I got this as undefined: this undefined

If I write the code this way, it will work:

async create(req: RequestWithBody<{ name: string }>, res: Response) {

        const { name } = req.body
        const type = AppDataSource.getRepository(Type).create({
            name
        })

        const createdType = await AppDataSource.getRepository(Type).save(type)
        return res.json(createdType)
    }

So I have no idea why "this" become undefined

  • does `router.post('/', (...args) => typeController.create(...args))` work? ` or `router.post('/', typeController.create.bind(typeController))` – Jaromanda X Aug 10 '23 at 08:52
  • the value of this within a method depends on how the method is invoked. When router.post('/', typeController.create), the create method being called without bound to the typeController instance, which is cause this to undefined – Hasan Raza Aug 10 '23 at 08:55
  • what if you use a constructor? ```constructor() { this.typeRepository = AppDataSource.getRepository(Type); }``` – GrafiCode Aug 10 '23 at 08:57
  • @JaromandaX yeah this actually work typeController.create.bind(typeController) – Vladyslav Geyna Aug 10 '23 at 08:59
  • yeah, `this` can be a harsh mistress depending on how the function is called – Jaromanda X Aug 10 '23 at 09:00
  • @GrafiCode I've tried this one as well. LickingFilth has solved this problem. That's because of typeController.create was passed as callback function in the router – Vladyslav Geyna Aug 10 '23 at 09:03

1 Answers1

0

When you pass typeController.create as a callback to router.post, this context inside the create method becomes undefined.

Simple solution: an arrow function, which binds this to the surrounding context :-)

create = async (req: RequestWithBody<{ name: string }>, res: Response) => {
        console.log('this', this)

        const { name } = req.body
        const type = this.typeRepository.create({
            name
        })
LickingFilth
  • 223
  • 1
  • 8