使用Typescript扩展快速请求对象

我试图添加一个属性来使用打字稿从中间件表示请求对象。 不过,我不知道如何添加额外的属性的对象。 如果可能,我宁愿不使用括号表示法。

我正在寻找一个解决scheme,让我写一些类似的东西(如果可能的话):

app.use((req, res, next) => { req.property = setProperty(); next(); }); 

在TypeScript中,接口是开放式的。 这意味着你可以从任何地方通过重新定义来为它们添加属性。

考虑到您正在使用这个express.d.ts文件,您应该能够重新定义请求界面以添加额外的字段。

 interface Request { property: string; } 

然后在你的中间件函数中, req参数也应该有这个属性。 您应该能够使用它,而不需要对代码进行任何更改。

您想要创build一个自定义定义,并在Typescript中使用一个名为“声明合并”的function。 这是常用的,例如在method-override

创build一个文件custom.d.ts ,并确保将其包含在你的tsconfig.json files如果有的话。 内容可以如下所示:

 declare namespace Express { export interface Request { tenant?: string } } 

这将允许你在你的代码中的任何地方使用这样的东西:

 router.use((req, res, next) => { req.tenant = 'tenant-X' next() }) router.get('/whichTenant', (req, res) => { res.status(200).send('This is your tenant: '+req.tenant) }) 

一个可能的解决scheme是使用“双重铸造任何”

1-与您的财产定义一个接口

 export interface MyRequest extends http.IncomingMessage { myProperty: string } 

2双投

 app.use((req: http.IncomingMessage, res: http.ServerResponse, next: (err?: Error) => void) => { const myReq: MyRequest = req as any as MyRequest myReq.myProperty = setProperty() next() }) 

双重铸造的优点是:

  • types是可用的
  • 它不污染现有的定义,但扩展它们,避免混淆
  • 由于投射是明确的,所以用-noImplicitany标志来编译罚款

或者,有快速(无types)的路线:

  req['myProperty'] = setProperty() 

(不要用你自己的属性编辑现有的定义文件 – 这是不可维护的,如果定义错误,打开一个拉取请求)

编辑

见下面的评论,简单的铸造在这种情况下req as MyRequest

我的2美分:像往常一样扩展当前types和代码。

 import { Request, Response, Router } from 'express' function handler(req: IRequest, res: Response, next: Function) { const authId = req.authId // ... } const router = Router() router.get('/', handler) // no compiling problems // this is just for ts, will disappear in transpilation interface IRequest extends Request { authId: string // example } 

您只需向全局Express命名空间声明任何新成员。 例:

 declare global { namespace Express { interface Request { context: Context } } } 

完整的例子:

 import * as express from 'express'; export class Context { constructor(public someContextVariable) { } log(message: string) { console.log(this.someContextVariable, { message }); } } declare global { namespace Express { interface Request { context: Context } } } const app = express(); app.use((req, res, next) => { req.context = new Context(req.url); next(); }); app.use((req, res, next) => { req.context.log('about to return') res.send('hello world world'); }); app.listen(3000, () => console.log('Example app listening on port 3000!')) 

更多

扩展全局命名空间在这里覆盖: https : //basarat.gitbooks.io/typescript/docs/types/lib.d.ts.html