node.js - Kan inte komma åt headers i utökad Express.Request-typ
Jag försöker utöka Express Request för att exakt typa hur en query kommer att se ut. Jag gör för närvarande detta på följande sätt:
export interface TypedRequestQuery<T> extends Express.Request {
query: T;
}
Detta fungerar till största delen, men vissa egenskaper verkar inte vara definierade. Till exempel:
(req as TypedRequestQuery<{data: string}>).headers
Fungerar inte. Det resulterar i följande fel:
Property 'headers' does not exist on type 'TypedRequestQuery<{ data: string; }>'
Jag har läst i flera källor att Express.Request är den korrekta typen för en requests args i en request handler. Men kanske missförstod jag? Att utelämna typningen av request handlern fungerar faktiskt!
router.get("/", async (req, res) => {
req.headers["x-forwarded-for"] // no errors
})
Och headers-egenskapen finns i req.
Jag använder passport.js vilket jag märkte ändrar definitionen av Request (eller åtminstone utökar den). Inte säker på om detta är orsaken.
Min fråga är: Är Express.Request rätt typ att utöka härifrån? Om det är det, varför verkar gränssnittet ofullständigt och hur kan jag fixa detta? Om inte, vilken typ bör jag utöka från?
Svar #1
Express' begärans typ låter dig redan definiera frågetypen...
export interface Request<
P = ParamsDictionary,
ResBody = any,
ReqBody = any,
ReqQuery = ParsedQs, // 👈
Locals extends Record<string, any> = Record<string, any>
> ...
Förfrågningstypen är den fjärde generiska, så du skulle behöva ange standardvärden för de första tre
import { ParamsDictionary, Request } from "express-serve-static-core";
type TypedRequestQuery<
TQuery,
TParams = ParamsDictionary,
TResBody = any,
TReqBody = any
> = Request<TParams, TResBody, TReqBody, TQuery>;
Då kan du använda det i dina rutter
router.get("/", async (req: TypedRequestQuery<{data: string}>, res) => {
console.log("headers[x-forwarded-for]:", req.headers["x-forwarded-for"]);
console.log("query[data]:", req.query.data);
res.send("I wish Typescript would let us skip generics");
})
Ditt exempel misslyckas med kompilering eftersom du försöker åsidosätta query-egenskapen med en inkompatibel typ
error TS2430: Interface 'TypedRequestQuery<T>' incorrectly extends interface 'Request<ParamsDictionary, any, any, ParsedQs, Record<string, any>>'. Types of property 'query' are incompatible. Type 'T' is not assignable to type 'ParsedQs'. interface TypedRequestQuery<T> extends Request { ~~~~~~~~~~~~~~~~~ interface TypedRequestQuery<T> extends Request { ~ This type parameter might need an `extends ParsedQs` constraint.
En kompatibel version skulle behöva ha din frågetyp utökad med ParsedQs
import { Request } from "express-serve-static-core";
import { ParsedQs } from "qs"
interface TypedRequestQuery<T extends ParsedQs> extends Request {
query: T;
}
