我正在尝试添加一个属性以使用Typescript从中间件表达请求对象。但是我不知道如何向对象添加额外的属性。如果可能的话,我宁愿不使用括号符号。
我正在寻找一种解决方案,允许我编写与此类似的内容(如果可能):
app.use((req, res, next) => {
req.property = setProperty();
next();
});
我正在尝试添加一个属性以使用Typescript从中间件表达请求对象。但是我不知道如何向对象添加额外的属性。如果可能的话,我宁愿不使用括号符号。
我正在寻找一种解决方案,允许我编写与此类似的内容(如果可能):
app.use((req, res, next) => {
req.property = setProperty();
next();
});
Answers:
您想要创建一个自定义定义,并在Typescript中使用一个称为声明合并的功能。这是常用的,例如在中method-override
。
创建一个文件custom.d.ts
,并确保将其包含在您tsconfig.json
的-部分中(files
如果有)。内容如下所示:
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)
})
files
节限制TypeScript包含的文件集。如果您未指定files
或include
,则*.d.ts
默认情况下将全部包含在内,因此无需在其中添加自定义类型。
Property 'tenant
不起作用:我在'Request'类型上不存在`如果我明确地将其包含在内,则没有任何区别tsconfig.json
。UPDATE随着declare global
作为@basarat pointet出在他的作品answear,但我不得不这样做import {Request} from 'express'
第一。
Request
在expressjs(至少4.x)中扩展对象的正确方法
如中的注释index.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!'))
对于较新版本的express,您需要扩展express-serve-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
}
}
'express'
模块却没有。谢谢!
import {Express} from "express-serve-static-core";
export {}
也可以使用。
express.d.ts
,否则编译器将尝试将其合并为快速的类型,从而导致错误。
接受的答案(与其他答案一样)对我不起作用,但是
declare module 'express' {
interface Request {
myProperty: string;
}
}
做到了。希望对别人有帮助。
custom-declarations.d.ts
文件放在TypeScript的项目根目录中,这对我也有效。
import { Request as IRequest } from 'express/index';
和interface Request extends IRequest
。还必须添加typeRoot
尝试了8个左右的答案但没有成功。我终于设法将它与jd291指向3mards repo的注释一起使用。
在名为的库中创建一个文件types/express/index.d.ts
。并在其中写道:
declare namespace Express {
interface Request {
yourProperty: <YourType>;
}
}
并将其包含在tsconfig.json
:
{
"compilerOptions": {
"typeRoots": ["./types"]
}
}
然后yourProperty
应可在每个请求下访问:
import express from 'express';
const app = express();
app.get('*', (req, res) => {
req.yourProperty =
});
提供的解决方案都不适合我。我最终只是扩展了Request接口:
import {Request} from 'express';
export interface RequestCustom extends Request
{
property: string;
}
然后使用它:
import {NextFunction, Response} from 'express';
import {RequestCustom} from 'RequestCustom';
someMiddleware(req: RequestCustom, res: Response, next: NextFunction): void
{
req.property = '';
}
编辑:TypeScript的最新版本对此有所抱怨。相反,我必须这样做:
someMiddleware(expressRequest: Request, res: Response, next: NextFunction): void
{
const req = expressRequest as RequestCustom;
req.property = '';
}
在TypeScript中,接口是开放式的。这意味着您可以从任何地方向它们添加属性,只需重新定义它们即可。
考虑到您正在使用这个express.d.ts文件,您应该能够重新定义Request接口以添加额外的字段。
interface Request {
property: string;
}
然后,在您的中间件函数中,req参数也应具有此属性。您应该能够使用它,而无需对代码进行任何更改。
Request.user = {};
在app.ts
如何userController.ts
认识呢?
express.Handler
(而不是手动指定(req: express.Request, res: express.Response, next: express.NextFunction) => any)
),它似乎不会引用相同的内容,Request
因为它抱怨我的属性不存在。
declare module "express"
,则不能declare namespace Express
。我宁愿使用名称空间语法,但对我而言不起作用。
虽然这是一个非常老的问题,但最近我偶然发现了这个问题。可以接受的答案很好,但是我需要向其中添加一个自定义接口Request
-我在代码中一直在使用的接口,但与接受的接口不能很好地工作回答。逻辑上,我尝试了这个:
import ITenant from "../interfaces/ITenant";
declare namespace Express {
export interface Request {
tenant?: ITenant;
}
}
但这是行不通的,因为Typescript将.d.ts
文件视为全局导入,并且当其中包含导入时,它们将被视为普通模块。这就是为什么上面的代码不适用于标准打字稿设置的原因。
这就是我最终要做的
// typings/common.d.ts
declare namespace Express {
export interface Request {
tenant?: import("../interfaces/ITenant").default;
}
}
// interfaces/ITenant.ts
export interface ITenant {
...
}
.d.ts
,tsconfig.json
以及使用实例?另外,由于从TS 2.9开始仅支持在全局模块中进行导入,因此您正在使用什么版本的打字稿?这可能会更好。
... "include": [ "src/**/*" ] ...
我有用, 但对我"include": ["./src/", "./src/Types/*.d.ts"],
无效。我还没有深入尝试了解这一点
也许这个问题已经解决了,但我只想分享一点,现在有时候像其他答案一样的界面可能有点过于严格,但是我们实际上可以维护所需的属性,然后通过创建一个与一种类型的键string
具有值类型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();
});
因此,现在,我们还可以向该对象添加任何其他想要的属性。
如果您正在寻找适用于express4的解决方案,则为:
@ types / express / index.d.ts:--------必须为/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参考
所有这些响应似乎都是错误的,或者在某种程度上已经过时了。
这对我来说是2020年5月的工作:
在${PROJECT_ROOT}/@types/express/index.d.ts
:
import * as express from "express"
declare global {
namespace Express {
interface Request {
my_custom_property: TheCustomType
}
}
}
在中tsconfig.json
,添加/合并属性,使得:
"typeRoots": [ "@types" ]
干杯。
一种可能的解决方案是对任何对象使用双重铸造
1-用你的财产定义一个接口
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()
(请勿使用您自己的属性编辑现有的定义文件-这是无法维护的。如果定义错误,请打开请求请求)
编辑
参见下面的评论,在这种情况下,简单的铸造作品 req as MyRequest
MyRequest
扩展了http.IncomingMessage
。事实并非如此,any
唯一的选择是双浇铸
这个答案对那些依赖npm package的人是有益的ts-node
。
我也一直在为扩展请求对象而苦恼,我在堆栈溢出中遵循了很多答案,并最终遵循了以下提到的策略。
我在以下目录中声明了express的扩展键入。${PROJECT_ROOT}/api/@types/express/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
编译器出了点问题。
更新开始script
在package.json
固定的对我来说。
"start": "ts-node --files api/index.ts",
在--files
参数方面发挥关键作用在这里找到确定的自定义类型定义。
有关更多信息,请访问:https : //github.com/TypeStrong/ts-node#help-my-types-are-missing
在2020年5月下旬尝试扩展ExpressJS的请求时,对我有用的就是帮助任何正在寻找其他尝试的人。在使此功能生效之前,我必须尝试了十几种方法:
"typeRoots": [
"./node_modules/@types",
"./your-custom-types-dir"
]
declare global {
namespace Express {
interface Request {
customBasicProperty: string,
customClassProperty: import("../path/to/CustomClass").default;
}
}
}
{
"restartable": "rs",
"ignore": [".git", "node_modules/**/node_modules"],
"verbose": true,
"exec": "ts-node --files",
"watch": ["src/"],
"env": {
"NODE_ENV": "development"
},
"ext": "js,json,ts"
}
这个答案可能已经很晚了,但是无论如何,这就是我的解决方法:
tsconfig
文件中包含类型源(这可能是一个全新的线程)express
express
目录内创建一个文件并命名index.d.ts
(必须完全一样)declare module 'express' {
export interface Request {
property?: string;
}
}