我在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;
}
...
}