我试图添加一个属性来表达使用typescript从中间件请求对象。但是,我不知道如何向对象添加额外的属性。如果可能的话,我宁愿不用括号。
我正在寻找一个解决方案,允许我写类似的东西(如果可能的话):
app.use((req, res, next) => {
req.property = setProperty();
next();
});
我试图添加一个属性来表达使用typescript从中间件请求对象。但是,我不知道如何向对象添加额外的属性。如果可能的话,我宁愿不用括号。
我正在寻找一个解决方案,允许我写类似的东西(如果可能的话):
app.use((req, res, next) => {
req.property = setProperty();
next();
});
当前回答
对我来说,一个简单的解决方案就是创建一个新的自定义接口来扩展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中。
也许这个问题已经有了答案,但我想分享一点, 有时候,像其他答案这样的界面可能有点太严格了, 但我们实际上可以维护所需的属性,然后通过创建值为any的字符串类型的键来添加任何要添加的其他属性
import { Request, Response, NextFunction } from 'express'
interface IRequest extends Request {
[key: string]: any
}
app.use( (req: IRequest, res: Response, next: NextFunction) => {
req.property = setProperty();
next();
});
现在,我们还可以向这个对象添加任何我们想要的属性。
虽然这是一个非常古老的问题,但我最近偶然发现了这个问题。接受的答案工作得很好,但我需要添加一个自定义接口请求-一个接口,我一直在我的代码中使用,并不能很好地与接受的答案。从逻辑上讲,我尝试了这样做:
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 {
...
}
你想要创建一个自定义定义,并使用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)
})
这个答案将有利于那些依赖npm包ts-node的人。
我也在与扩展请求对象同样的问题作斗争,我在堆栈溢出中遵循了许多答案,并以遵循下面提到的策略结束。
我在以下目录中声明了express的扩展类型。$ {PROJECT_ROOT} / api / @types /快递/ index.d.ts
declare namespace Express {
interface Request {
decoded?: any;
}
}
然后更新我的tsconfig。Json变成这样。
{
"compilerOptions": {
"typeRoots": ["api/@types", "node_modules/@types"]
...
}
}
即使在执行上述步骤之后,visual studio也不再抱怨,但不幸的是,ts-node编译器仍然习惯抛出。
Property 'decoded' does not exist on type 'Request'.
显然,ts-node无法定位请求对象的扩展类型定义。
最终,在花了几个小时后,我知道VS Code并没有抱怨,并且能够找到类型定义,这意味着ts-node编译器有问题。
正在更新包中的开始脚本。Json为我解决了这个问题。
"start": "ts-node --files api/index.ts",
——files参数在这里起着关键作用,确定自定义类型定义。
欲了解更多信息,请访问:https://github.com/TypeStrong/ts-node#help-my-types-are-missing