英文:
Can not access headers in extended Express.Request type
问题
我试图扩展Express的Request
类型,以确切描述查询的外观。我目前是这样做的:
export interface TypedRequestQuery<T> extends Express.Request {
query: T;
}
这在大部分情况下都可以工作,但有些属性似乎未定义。例如:
(req as TypedRequestQuery<{data: string}>).headers
不起作用。它会产生以下错误:
属性'headers'在类型'TypedRequestQuery<{ data: string; }>'上不存在
我在多个来源中看到过,Express.Request
是请求处理程序的请求参数的正确类型。但也许我理解错了?省略请求处理程序的类型注解确实起作用:
router.get("/", async (req, res) => {
req.headers["x-forwarded-for"] // 没有错误
})
而且req
中存在headers
属性。
我正在使用passport.js
,我注意到它更改了Request
的定义(或至少是扩展了它)。不确定这是否是原因。
我的问题是:Express.Request
是应该在此基础上进行扩展的正确类型吗?如果是,为什么接口看起来不完整,我应该如何解决这个问题?如果不是,我应该从哪种类型进行扩展?
英文:
I am trying to extend Express' Request
to type exactly what a query will look like. I currently do this as follows:
export interface TypedRequestQuery<T> extends Express.Request {
query: T;
}
This works for the most part, but some properties do not seem to be defined. For example:
(req as TypedRequestQuery<{data: string}>).headers
Does not work. It results in the following error:
Property 'headers' does not exist on type 'TypedRequestQuery<{ data: string; }>'
I have read in multiple sources that Express.Request
is the correct type for a request handler's request argument. But maybe I misunderstood? Leaving out the typings of the request handler does work!:
router.get("/", async (req, res) => {
req.headers["x-forwarded-for"] // no errors
})
And the headers
property is present in the req
.
I am using passport.js
which I noticed changes the definition of Request
(or at least extends it). Not sure if this is the cause.
My question is: Is Express.Request
the correct type to be extending from here? If it is, why does the interface seem incomplete and how can I fix this? If not, what type should I extend from?
答案1
得分: 1
Express的Request类型已经允许你定义查询类型...
export interface Request<
P = ParamsDictionary,
ResBody = any,
ReqBody = any,
ReqQuery = ParsedQs, // 👈
Locals extends Record<string, any> = Record<string, any>
> ...
查询类型是第四个泛型参数,所以你需要为前三个提供默认值
import { ParamsDictionary, Request } from "express-serve-static-core";
type TypedRequestQuery<
TQuery,
TParams = ParamsDictionary,
TResBody = any,
TReqBody = any
> = Request<TParams, TResBody, TReqBody, TQuery>;
然后你可以在你的路由中使用它
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("我希望Typescript能让我们跳过泛型参数");
})
你的示例编译失败,因为你尝试使用不兼容的类型覆盖query
属性
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.
一个兼容的版本需要让你的查询类型扩展ParsedQs
import { Request } from "express-serve-static-core"
import { ParsedQs } from "qs"
interface TypedRequestQuery<T extends ParsedQs> extends Request {
query: T;
}
英文:
Express' Request type already lets you define the query type...
export interface Request<
P = ParamsDictionary,
ResBody = any,
ReqBody = any,
ReqQuery = ParsedQs, // 👈
Locals extends Record<string, any> = Record<string, any>
> ...
The query type is the 4th generic so you'd need to provide defaults for the first three
import { ParamsDictionary, Request } from "express-serve-static-core";
type TypedRequestQuery<
TQuery,
TParams = ParamsDictionary,
TResBody = any,
TReqBody = any
> = Request<TParams, TResBody, TReqBody, TQuery>;
Then you can use it in your routes
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");
})
Your example fails compilation because you're trying to override the query
property with an incompatible type
> none
> 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.
>
A compatible version would need to have your query type extend ParsedQs
import { Request } from "express-serve-static-core";
import { ParsedQs } from "qs"
interface TypedRequestQuery<T extends ParsedQs> extends Request {
query: T;
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论