Расширить объект Express Request с помощью TypScript
Я пытаюсь добавить свойство для выражения объекта запроса из промежуточного программного обеспечения с помощью машинописного текста. Однако я не могу понять, как добавить дополнительные объекты к объекту. Я предпочел бы, если возможно, использовать нотацию с кронштейнами.
Я ищу решение, которое позволило бы мне написать что-то похожее на это (если возможно):
app.use((req, res, next) => { req.property = setProperty(); next(); });
- Использование TypeScript в существующем проекте Visual Studio Web Site
- Успешная assembly с множеством ошибок в машинописных файлах с машинописными текстами
В TypeScript интерфейсы открыты. Это означает, что вы можете добавлять к ним свойства из любого места, просто переопределяя их.
Учитывая, что вы используете этот файл express.d.ts , вы должны переопределить интерфейс Request, чтобы добавить дополнительное поле.
interface Request { property: string; }
Затем в вашей функции промежуточного программного обеспечения параметр req должен также иметь это свойство. Вы можете использовать его без каких-либо изменений в коде.
Вы хотите создать собственное определение и использовать функцию в машинописном названии « Слияние слияния» . Это обычно используется, например, в method-override
.
Создайте файл custom.d.ts
и обязательно custom.d.ts
его в files
tsconfig.json
если они есть. Содержимое может выглядеть следующим образом:
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) })
Вы просто объявляете глобальное пространство имен 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!'))
Больше
Расширение глобальных пространств имен описано здесь: https://basarat.gitbooks.io/typescript/docs/types/lib.d.ts.html
Мои 2 цента: Расширьте текущий тип и код, как обычно.
import { Request, Response, Router } from 'express' function handler(req: IRequest, res: Response, next: Function) { const authId = req.authId // ... } const router = Router() router.get('/', handler) // no compiling problems // this is just for ts, will disappear in transpilation interface IRequest extends Request { authId: string // example }
Одним из возможных решений является использование «двойного литья в любой»,
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 {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 = ''; }
Принимаемый ответ (как и другие) не работает для меня, но
declare module 'express' { interface Request { myProperty: string; } }
сделал. Надеюсь, что это поможет кому-то.