Nodejs + typescript class inheritance



我在typescript+expressjs中构建一个简单的休息api。我想用类来构建它,但我被困在路由类的部分。我的想法是构建一个基类(baseRouter(,它可以由特定的路由器(IndexRouter(扩展。但是尝试这样做,我最终从baseRouter而不是IndexRouter注册路由。我做错了什么?

export class baseRouter {
    protected static _inst: baseRouter;
    protected _router: express.Router;
    protected _routeBase: string = "/base";
    protected constructor() { }
    public static route(router: express.Router) {
        if (typeof this._inst === 'undefined') this._inst = new this();
        this._inst._router = router;
        this._inst._registerRoutes();
    }
    protected _registerRoutes() {
        this._router.get(this._routeBase, this._doGet);
        console.log('Calling base route');
    }
    protected _doGet(req: express.Request, res: express.Response) {
        res.status(200);
        res.send('isBase');
    }
}
export class indexRouter extends baseRouter {
    protected _routeBase = "/index";
    protected _registerRoutes() {
        this._router.get(this._routeBase, this._doGet);
        console.log('Calling index route');
    }
    protected _doGet(req: express.Request, res: express.Response) {
        res.status(200);
        res.send('isIndex');
    }
    protected _doPost(req: express.Request, res: express.Response) {
        res.status(200);
        res.send('isIndexPost');
    }
}

这两个类的入口方法是.route(router(。理想情况下,我的理解解决方案将是这样的:

BaseRouter.route() -> calls baseRouter._registerRoutes() -> ...
IndexRouter.route() -> calls indexRouter._registerRoutes() -> ...

这是否可以在不每次都重新声明 .route(( 函数的情况下实现?

问题出在以下行上:

if (typeof this._inst === 'undefined') this._inst = new this();

首次调用BaseRouter.route()此行设置静态成员BaseRouter._inst
但是由于IndexRouter扩展BaseRouter它也继承了静态成员,因此IndexRouter._inst也存在,因此在该行中不会创建IndexRouter的实例。

它在游乐场中运行良好的原因是它针对es5,而您可能针对es6
不同之处在于,当面向es6时,类将被转换为静态行为不同的es6类。

要解决此问题,您可以执行以下操作:

public static route() {
    if (typeof this._inst === 'undefined' || this._inst.constructor !== this) this._inst = new this();
    this._inst._registerRoutes();
}

编辑

据我所知,拥有"静态多态这个成员"没有任何技巧,例如这失败了:

class BaseRouter<T extends BaseRouter<any>> {
    protected static _inst: T;
    ...
}

因为:

Static members cannot reference class type parameters

所以我很确定你必须坚持:static _inst: baseRouter.

您可以尝试在 IndexRouter 中重新声明成员:

class IndexRouter extends BaseRouter {
    protected static _inst: IndexRouter;
    ...
}

你也可以有一个通用的吸气剂:

class BaseRouter {
    private static _inst: BaseRouter;
    protected static _getInstance<T extends BaseRouter>(): T {
        return this._inst as T;
    }
    ...
}

最新更新