我试图添加一个属性来表达使用typescript从中间件请求对象。但是,我不知道如何向对象添加额外的属性。如果可能的话,我宁愿不用括号。

我正在寻找一个解决方案,允许我写类似的东西(如果可能的话):

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

当前回答

所有这些回答在某种程度上似乎都是错误的或过时的。

这在2020年5月对我有效:

在$ {PROJECT_ROOT} / @types /快递/ index.d.ts:

import * as express from "express"

declare global {
    namespace Express {
        interface Request {
            my_custom_property: TheCustomType
        }
    }
}

在tsconfig。Json,添加/合并属性,使:

"typeRoots": [ "@types" ]

欢呼。

其他回答

你想要创建一个自定义定义,并使用Typescript中称为声明合并的特性。这是常用的,例如在方法重写中。

创建一个custom.d.ts文件,并确保将其包含在tsconfig中。Json的文件节(如果有的话)。内容如下所示:

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)
})

对于较新的express版本,您需要增强express- service -static-core模块。

这是必需的,因为现在Express对象来自那里:https://github.com/DefinitelyTyped/DefinitelyTyped/blob/8fb0e959c2c7529b5fa4793a44b41b797ae671b9/types/express/index.d.ts#L19

基本上,使用以下方法:

declare module 'express-serve-static-core' {
  interface Request {
    myField?: string
  }
  interface Response {
    myField?: string
  }
}

这招对我很管用:

declare namespace e {
    export interface Request extends express.Request {
        user:IUserReference,
        [name:string]:any;
    }
    export interface Response extends express.Response {
        [name:string]:any;
    }
}



export type AsyncRequestHandler = (req:e.Request, res:e.Response, logger?:Logger) => Promise<any>|Promise<void>|void;
export type AsyncHandlerWrapper = (req:e.Request, res:e.Response) => Promise<void>;

我在代码中使用了它,比如以这样的方式导出具有这样签名的函数:

app.post('some/api/route', asyncHandlers(async (req, res) => {
        return await serviceObject.someMethod(req.user, {
            param1: req.body.param1,
            paramN: req.body.paramN,
            ///....
        });
    }));

一个可能的解决方案是使用“double casting to any”

用你的属性定义一个接口

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()
})

双铸造的优点是:

类型是可用的 它不会污染现有的定义,而是扩展了它们,避免了混淆 由于强制转换是显式的,它编译带有-noImplicitany标志的罚金

或者,还有一个快速(无类型)路由:

 req['myProperty'] = setProperty()

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

EDIT

参见下面的评论,在这种情况下,简单的强制转换工作需要MyRequest

公认的答案(和其他答案一样)对我不适用,但是

declare module 'express' {
    interface Request {
        myProperty: string;
    }
}

所做的。希望这能帮助到一些人。