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

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

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

当前回答

对于较新的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
  }
}

其他回答

在2021年,这个方法是有效的:

在express 4.17.1中,https://stackoverflow.com/a/55718334/9321986和https://stackoverflow.com/a/58788706/9321986的组合工作:

在类型/快递/ index.d.ts:

declare module 'express-serve-static-core' {
    interface Request {
        task?: Task
    }
}

在tsconfig.json中:

{
    "compilerOptions": {
        "typeRoots": ["./types"]
    }
}

.d。Ts声明是黑客。简单地接受这样一个事实:express的中间件系统不适合typescript。所以不要用它。

错误代码示例:

const auth = (req) => {
  const user = // parse user from the header

  if(!user)
     return res.status(401).send({ result: 'unauthorized-error' })

  req.user = user
  return next()
}

app.get('/something', auth, (req, res) => {
  // do something
})

更好的代码:

const auth = (req) => {
  return // parse user from the header
}

app.get('/something', (req, res) => {
  const user = auth(req)
  if(!user)
    return res.status(401).send({ result: 'unauthorized-error' })
  // do something
})

你可以使用更高阶的函数来恢复中间件的使用:

Const auth = (req) => { 从头文件返回// parse user } const withUser =(回调:(foo, req, res) => void) => (req, res) => { Const user = auth(req) 如果用户(!) 返回res.status(401)。发送({result: 'unauthorized-error'}) 返回回调(user, req, res) } app.get('/something', withUser((user, req, res) => { //做某事 }))

如果你愿意,你甚至可以把它们堆叠起来:

const withFoo = (callback) => (req, res) => { /* ... */ } const withBar = (callback) => (req, res) => { /* ... */ } const withBaz = (callback) => (req, res) => { /* ... */ } const withFooBarAndBaz = (callback) => (req,res) => { withFoo((foo) => withBar((bar) => withBaz((baz) => callback({ foo, bar, baz }, req, res) )(req,res) )(req,res) )(req,res) } app.get('/something', withFooBarAndBaz(({ foo, bar, baz }, req, res) => { // do something with foo, bar and baz }))

只要使用语言,而不是表达促进的不安全突变。

编辑:我使用第一个建议的解决方案。但不同的是,我的auth函数抛出了一个错误,我可以捕捉并返回正确的响应,所以我不需要在控制器中这样做。例如:

app.get('/something', withResponse((req) => {
   const user = auth(req)
   return success({
     message: `Hi ${user.name}`
   })
}))

我还发送返回类型,而不是手动调用res.send。它还允许我输入响应。我建议你也去查查tRPC。

在尝试了8个左右的答案,没有成功。我终于设法让它与jd291的评论指向3mards回购工作。

在基库中创建一个名为types/express/index.d.ts的文件。在信中写道:

declare namespace Express {
    interface Request {
        yourProperty: <YourType>;
    }
}

并将其包含在tsconfig中。json:

{
    "compilerOptions": {
        "typeRoots": ["./types"]
    }
}

那么你的属性应该在每个请求下都是可访问的:

import express from 'express';

const app = express();

app.get('*', (req, res) => {
    req.yourProperty = 
});

对于简单的情况,我在外部中间件中使用headers属性,然后在内部中间件中获得它。

// outer middleware
req.headers["custom_id"] = "abcxyz123";

// inner middleware
req.get("custom_id");

缺点:

只能存储字符串。如果您想存储其他类型,如json或number,您可能必须稍后解析它。 headers属性没有文档化。Express只记录了req.get()方法。因此,您必须使用与属性头文件一起工作的Express的确切版本。

现在回答这个问题可能已经很晚了,但无论如何,我是这样解决的:

确保在tsconfig文件中包含了类型的源代码(这可能是一个全新的线程) 在types目录中添加一个新目录,并将其命名为要为其扩展或创建类型的包。在本例中,您将创建一个名为express的目录 在express目录中创建一个文件,并将其命名为index.d.ts(必须与此完全相同) 最后,为了扩展类型,你只需要放如下代码:

declare module 'express' {
    export interface Request {
        property?: string;
    }
}