You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript类继承调用方法时出现TypeError的原因与解决

TypeScript继承调用基类方法时出现TypeError问题排查与解决

错误信息

TypeError: Cannot read properties of undefined (reading 'Ok')

代码片段

SettingController.ts

import { Request, Response, NextFunction } from 'express';
// ... 其他导入

export default new class SettingController extends BaseController {

    constructor() {
        super();
    }

    async SettingOTP(req: Request, res: Response, next: NextFunction) {
        try {
            // ... 一些操作
            return this.Ok(res, 'OTP setting updated successfully');
        } catch (error: any) {
            this.BadRerquest(res, error.message);
        }
    }

    // ... 其他方法
}

BaseController.ts

import { Response } from 'express';
// ... 其他导入

export class BaseController {
    
    // ... 构造函数及其他方法
    
    Ok<T>(res: Response, message: string) {
        return new SuccessResponse(message).send(res);
    }
}

路由代码

import express, { Express, Router, NextFunction, Request, Response } from 'express';

import SettingController from '../../http/controller/SettingController';

// const setting_controller = new SettingController(new SettingService());

const settingRouter = express.Router();
// settingRouter.get('/get', settingController.getSetting);
settingRouter.put('/opt-setting', SettingController.SettingOTP);

已尝试操作

  • 确认BaseController已正确导入,Ok方法未被重写
  • 在SettingController构造函数中尝试绑定方法,TypeScript编译无异常

问题核心

为何调用this.Ok会触发TypeError?如何正确使用TypeScript继承的方法?


原因分析

问题根源是方法传递时this上下文丢失:当你把SettingController.SettingOTP直接作为路由处理函数传给Express时,该方法的this不再指向SettingController实例,而是变成undefined(Express调用路由函数时不会自动绑定原实例的上下文)。即便你用new class导出单例实例,单独提取方法传递依然会丢失this绑定。

解决方法

提供三种可行方案:

方案1:构造函数内手动绑定方法到实例

修改SettingController构造函数,将方法绑定到当前实例,确保this指向正确:

export default new class SettingController extends BaseController {
    constructor() {
        super();
        // 绑定方法到实例
        this.SettingOTP = this.SettingOTP.bind(this);
        // 其他需要调用基类方法的函数也需同理绑定
    }

    async SettingOTP(req: Request, res: Response, next: NextFunction) {
        try {
            return this.Ok(res, 'OTP setting updated successfully');
        } catch (error: any) {
            this.BadRerquest(res, error.message);
        }
    }
}

方案2:用箭头函数定义方法

箭头函数会自动捕获当前上下文的this,不会出现绑定丢失问题:

export default new class SettingController extends BaseController {
    constructor() {
        super();
    }

    // 箭头函数定义方法,自动绑定this
    SettingOTP = async (req: Request, res: Response, next: NextFunction) => {
        try {
            return this.Ok(res, 'OTP setting updated successfully');
        } catch (error: any) {
            this.BadRerquest(res, error.message);
        }
    }
}

方案3:路由中用箭头函数包裹调用

注册路由时,通过箭头函数包裹方法调用,强制保留实例上下文:

settingRouter.put('/opt-setting', (req, res, next) => SettingController.SettingOTP(req, res, next));

内容的提问来源于stack exchange,提问作者Mr Coder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 11:29:57