首页 > 解决方案 > 无法读取构造类的属性

问题描述

我对 TypeScript 还很陌生,最近遇到了一个我无法解决的问题。

我正在使用 Express 创建一个 REST API。我有一个路由器,它调用一个控制器,在控制器内部,我调用一个服务的方法,然后返回响应。

这是我的路由器的外观:

import express from 'express';

import { BidsController } from '../../controllers/bids.controller';

const router = express.Router();
const bidsController = new BidsController();

router.post('/bids', isAuthenticated, checkRoles(['user']), checkIsVerified, bidsController.createBid);

路由器有一些中间件,但它们都没有使用bidsController,所以我相信它们不会导致错误。

这是我的bidsController:

import validator from '../validator';
import { BidsService } from '../services/bids.service';

class BidsController implements IBidsController {
  bidsService;

  constructor() {
    this.bidsService = new BidsService();
  }

  async createBid(req: Request, res: Response, next: NextFunction): Promise<void> {
    const { params, body } = req;

    try {
      validator.bids.create(params, body);

      const { userId } = res.locals.tokenInfo;
      const { value } = body;

      const response = await this.bidsService.createBid(value, userId);
      res.status(201).json(response);
    } catch (exception) {
      next(exception);
    }
  }
}

这是服务:

class BidsService implements IBidsService {
  public async createBid(value: number, userId: string): Promise<IBid> {
    const bid = new Bid({
      value,
      user: userId,
    })

    await bid.save();

    return bid;
  }
}

因此,当我使用 Postman 调用 POST /bids 端点时,我收到错误消息:

"TypeError: Cannot read property 'bidsService' of undefined"

你能帮我解决这个问题吗?

标签: javascriptnode.jstypescriptexpress

解决方案


router.post('/bids', isAuthenticated, checkRoles(['user']), 
checkIsVerified, bidsController.createBid.bind(bidsController)); // <- THE FIX

首先,这是一个 JS 运行时错误,与 TS 无关。

this关键字是在调用对象的“方法”时动态确定的。

通常你直接调用那个对象的方法,比如bidsController.createBid(). 这会将this里面的关键字绑定createBidbidsController.

但是,在您的情况下,您不会直接调用它。相反,您只需将 的值bidsController.createBid(一个函数)router.post作为回调传递给稍后将被调用的回调。

在这种this情况下,关键字是未绑定的,因为稍后调用它时,它没有任何关于bidsController. 为了提供该信息,您使用bidsController.createBid.bind(bidsController)预先绑定它。

另一种提前绑定的方法是在声明类方法时使用箭头函数。

class BidsController implements IBidsController {

  createBid = async (req: Request, res: Response, next: NextFunction) => {
    const { params, body } = req;


推荐阅读