我试图添加一个属性来表达使用typescript从中间件请求对象。但是,我不知道如何向对象添加额外的属性。如果可能的话,我宁愿不用括号。
我正在寻找一个解决方案,允许我写类似的东西(如果可能的话):
app.use((req, res, next) => {
req.property = setProperty();
next();
});
我试图添加一个属性来表达使用typescript从中间件请求对象。但是,我不知道如何向对象添加额外的属性。如果可能的话,我宁愿不用括号。
我正在寻找一个解决方案,允许我写类似的东西(如果可能的话):
app.use((req, res, next) => {
req.property = setProperty();
next();
});
当前回答
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中。
其他回答
我也有同样的问题,我是这样解决的:
// /src/types/types.express.d.ts
declare namespace Express {
export interface Request {
user: IUser
}
}
但有一些条件是必须的!
添加到tsconfig。json配置
"paths": {
"*": [
"node_modules/*",
"src/types/*"
]
},
在此之后,tsc将构建bundle,而ts-node则不会。
必须在编译器命令中添加——files
ts-node --files src/server.ts
只需将属性添加到req。params对象。
req.params.foo = "bar"
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中。
这就是我在使用Nestjs和Express时的工作方式。截至2020年11月。
创建一个文件:./@types/express- server -static-core/index.d.ts
注意:必须有上面的路径和文件名。这样Typescript声明合并就可以了。
import { UserModel } from "../../src/user/user.model";
declare global{
namespace Express {
interface Request {
currentUser: UserModel
}
}
}
将其添加到tsconfig.json中
"typeRoots": [
"@types",
"./node_modules/@types",
]
一个可能的解决方案是使用“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