TypeScriptを使用してミドルウェアからのリクエストオブジェクトを表現するプロパティを追加しようとしています。ただし、オブジェクトに追加のプロパティを追加する方法がわかりません。可能であれば、ブラケット表記を使用しないことを希望します。
私はこれに似たものを書くことを可能にするソリューションを探しています(可能であれば):
app.use((req, res, next) => {
req.property = setProperty();
next();
});
カスタム定義を作成し、TypeScriptの Declaration Merging という機能を使用します。これは一般的に使用されています。 in 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)
})
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でさらに詳しく 。
受け入れられた答え(他の人として)は私にはうまくいきませんが、
declare module 'express' {
interface Request {
myProperty: string;
}
}
した。それが誰かを助けることを願っています。
提供されたソリューションはどれも私にとってはうまくいきませんでした。私は単に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 = '';
}
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
}
}
TypeScriptでは、インターフェースはオープンエンドです。つまり、プロパティを再定義するだけで、どこからでもプロパティを追加できます。
この express.d.ts ファイルを使用していることを考慮すると、Requestインターフェースを再定義して、余分なフィールド。
interface Request {
property: string;
}
ミドルウェア関数では、reqパラメーターにもこのプロパティが必要です。コードを変更せずに使用できるはずです。
可能な解決策の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
これは非常に古い質問ですが、最近この問題に出くわしました。受け入れられた答えは問題なく動作しますが、カスタムインターフェイスを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 {
...
}