typescriptを使用してミドルウェアからリクエストオブジェクトを表現するプロパティを追加しようとしています。ただし、オブジェクトにプロパティを追加する方法がわかりません。できればブラケット表記は使わない方がいいです。
私はこれに似たものを書くことができる解決策を探しています(可能な場合):
app.use((req, res, next) => {
req.property = setProperty();
next();
});
typescriptを使用してミドルウェアからリクエストオブジェクトを表現するプロパティを追加しようとしています。ただし、オブジェクトにプロパティを追加する方法がわかりません。できればブラケット表記は使わない方がいいです。
私はこれに似たものを書くことができる解決策を探しています(可能な場合):
app.use((req, res, next) => {
req.property = setProperty();
next();
});
回答:
カスタム定義を作成し、TypescriptでDeclaration Mergingと呼ばれる機能を使用したいとします。これは、たとえばで一般的に使用されmethod-override
ます。
ファイルを作成custom.d.ts
して、それを含めるようにしてくださいtsconfig.json
さんfiles
-sectionがあれば。内容は次のようになります。
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!'))
グローバル名前空間の拡張については、私のGitBookで詳しく説明しています。
新しいバージョンの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かそこらの答えを試してみましたが、成功していません。3mardsリポジトリを指し示すjd291のコメントを使用して、なんとか動作させることができました。
と呼ばれるベースにファイルを作成します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
ファイルをグローバルインポートとして扱い、インポートがある場合は通常のモジュールとして扱われるため、これは機能しませんでした。上記のコードが標準のtypescript設定で機能しないのはそのためです。
これが私がやったことです
// 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以降でのみサポートされているため、使用しているtypescriptのバージョンは何ですか?それはより良い助けになるでしょう。
... "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つは、「任意へのダブルキャスト」を使用することです。
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パッケージに依存しているユーザーにとって有益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コードは文句を言わず、型定義を見つけることができたので、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;
}
}