node.js - ¿Cómo agrego una propiedad personalizada a Express.Request en Typescript?
Lo siento por mis pobres habilidades en inglés.
Creé un nuevo proyecto usando express-generator-typescript.
$ npx express-generator-typescript --use-yarn
Quiero agregar propiedades adicionales a Express.Request para mi middleware personalizado. Así que creé types/myRequest.d.ts en ./src y guardé el código como se muestra a continuación:
// myRequest.d.ts
declare namespace Express {
interface Request {
myProp?: boolean;
}
}
Y descomenté "typeRoots" en tsconfig.json y añadí "./node_modules/@types", "./src/types", e intenté usar la propiedad añadida creando un middleware en ./src/routes/api.ts. Aquí está el código completo:
// api.ts
import { NextFunction, Request, Response, Router } from "express";
import userRouter from "./user-router";
function myMiddleware(req: Request, _res: Response, next: NextFunction) {
req.myProp = true;
next();
}
// Export the base-router
const baseRouter = Router();
// Setup routers
baseRouter.use("/users", myMiddleware, userRouter);
// Export default.
export default baseRouter;
Esto se compila bien, además IntelliSense en VS Code funciona correctamente y no muestra ningún problema. Sin embargo, cuando ejecuto yarn start:dev obtengo el siguiente error:
/home/me/dev/express-gen-ts/node_modules/ts-node/src/index.ts:828
return new TSError(diagnosticText, diagnosticCodes);
^
TSError: ⨯ Unable to compile TypeScript:
src/routes/api.ts:5:7 - error TS2339: Property 'myProp' does not exist on type 'Request<ParamsDictionary, any, any, ParsedQs, Record<string, any>>'.
5 req.myProp = true;
~~~~~~
at createTSError (/home/me/dev/express-gen-ts/node_modules/ts-node/src/index.ts:828:12)
at reportTSError (/home/me/dev/express-gen-ts/node_modules/ts-node/src/index.ts:832:19)
at getOutput (/home/me/dev/express-gen-ts/node_modules/ts-node/src/index.ts:1022:36)
at Object.compile (/home/me/dev/express-gen-ts/node_modules/ts-node/src/index.ts:1326:43)
at Module.m._compile (/home/me/dev/express-gen-ts/node_modules/ts-node/src/index.ts:1458:30)
at Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
at Object.require.extensions.<computed> [as .ts] (/home/me/dev/express-gen-ts/node_modules/ts-node/src/index.ts:1462:12)
at Module.load (node:internal/modules/cjs/loader:981:32)
at Function.Module._load (node:internal/modules/cjs/loader:822:12)
at Module.require (node:internal/modules/cjs/loader:1005:19) {
diagnosticCodes: [ 2339 ]
}
[nodemon] app crashed - waiting for file changes before starting...
Así que no puedo hacer desarrollo en el estado de desarrollo. Por supuesto, si no uso propiedades adicionales, el estado de desarrollo también está disponible y funciona bien.
Creo que express-generator-typescript en sí mismo tiene alguna configuración. Porque cambiar "typeRoots" en tsconfig.json no cambia el resultado. Pero no pude encontrarla.
Gracias de antemano.
Respuesta #1
Siempre que me encuentro con este tipo de problema, generalmente uso "declare module" para agregar propiedades a la interfaz "Request" de Express en lugar de declararlas en un namespace. De esta manera, generalmente no tengo que cambiar nada en el tsconfig ni agregar archivos .d.ts.
Agrega estas líneas a tu código api.ts (ten en cuenta que en la mayoría de los casos necesitarás referenciar el módulo express-serve-static-core ya que es aquí donde se declara la interfaz Request):
declare module "express-serve-static-core" {
interface Request {
myProp?: boolean;
}
}
Archivo completo:
// api.ts
import { NextFunction, Request, Response, Router } from "express";
import userRouter from "./user-router";
declare module "express-serve-static-core" {
interface Request {
myProp?: boolean;
}
}
function myMiddleware(req: Request, _res: Response, next: NextFunction) {
req.myProp = true;
next();
}
// Export the base-router
const baseRouter = Router();
// Setup routers
baseRouter.use("/users", myMiddleware, userRouter);
// Export default.
export default baseRouter;
Normalmente, esto debería hacer que su propiedad recién añadida esté disponible en otros archivos también, pero, por supuesto, puede exportar la interfaz Request manipulada solo para estar seguro.
Respuesta #2
Te sugiero una manera y espero que te ayude.
en el archivo ./src/routes/api.ts agregas este código (debajo de import)
declare global {
namespace Express {
interface Request {
myProp?: boolean;
}
}
}
entonces ejecuta de nuevo (no parece necesitar el archivo types/myRequest.d.ts)
