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

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

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

当前回答

这招对我很管用:

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,
            ///....
        });
    }));

其他回答

虽然这是一个非常古老的问题,但我最近偶然发现了这个问题。接受的答案工作得很好,但我需要添加一个自定义接口请求-一个接口,我一直在我的代码中使用,并不能很好地与接受的答案。从逻辑上讲,我尝试了这样做:

import ITenant from "../interfaces/ITenant";

declare namespace Express {
    export interface Request {
        tenant?: ITenant;
    }
}

但这不起作用,因为Typescript处理。d。Ts文件作为全局导入,当它们中有导入时,它们被视为普通模块。这就是为什么上面的代码不能在标准的typescript设置下工作。

这是我最后做的事情

// typings/common.d.ts

declare namespace Express {
    export interface Request {
        tenant?: import("../interfaces/ITenant").default;
    }
}
// interfaces/ITenant.ts

export interface ITenant {
    ...
}

在mac节点12.19.0和express 4上,使用护照进行身份验证,我需要扩展我的Session对象

与上面相似,但略有不同:

import { Request } from "express";


declare global {
  namespace Express {
    export interface Session {
      passport: any;
      participantIds: any;
      uniqueId: string;
    }
    export interface Request {
      session: Session;
    }
  }
}

export interface Context {
  req: Request;
  user?: any;
}```

对我来说,一个简单的解决方案就是创建一个新的自定义接口来扩展express Request。 这个接口应该包含所有可选的自定义req属性。 将此接口设置为中间件请求的类型。

// ICustomRequset.ts
   import { Request } from "express"
   export default interface ICustomRequset extends Request {
       email?: string;
       roles?: Array<string>;
   }

// AuthMiddleware.ts
...
export default async function (
  req: ICustomRequset,
  res: Response,
  next: NextFunction
) {
  try {
      // jwt code
      req.email=jwt.email
      req.roles=jwt.roles
      next()
  }catch(err){}

d.从索引中的注释中可以看出。ts时,只需向全局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!'))

More

扩展全局名称空间也包含在TypeScript Deep Dive中。

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

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

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

缺点:

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