我试图添加一个属性来表达使用typescript从中间件请求对象。但是,我不知道如何向对象添加额外的属性。如果可能的话,我宁愿不用括号。
我正在寻找一个解决方案,允许我写类似的东西(如果可能的话):
app.use((req, res, next) => {
req.property = setProperty();
next();
});
我试图添加一个属性来表达使用typescript从中间件请求对象。但是,我不知道如何向对象添加额外的属性。如果可能的话,我宁愿不用括号。
我正在寻找一个解决方案,允许我写类似的东西(如果可能的话):
app.use((req, res, next) => {
req.property = setProperty();
next();
});
当前回答
在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;
}```
其他回答
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中。
在TypeScript中,接口是开放的。这意味着只需重新定义它们,就可以从任何地方向它们添加属性。
考虑到您正在使用这个express.d.ts文件,您应该能够重新定义Request接口以添加额外的字段。
interface Request {
property: string;
}
然后在中间件函数中,req参数也应该具有此属性。您应该能够在不修改代码的情况下使用它。
在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"]
}
}
如果您正在寻找与express4一起工作的解决方案,下面是:
@types /快递/ index.d。--------必须是/index.d.ts
declare namespace Express { // must be namespace, and not declare module "Express" {
export interface Request {
user: any;
}
}
tsconfig.json:
{
"compilerOptions": {
"module": "commonjs",
"target": "es2016",
"typeRoots" : [
"@types", // custom merged types must be first in a list
"node_modules/@types",
]
}
}
参考资料来自https://github.com/TypeStrong/ts-node/issues/715#issuecomment-526757308
.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。