使用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