无法访问扩展的Express.Request类型中的标头

huangapple go评论98阅读模式
英文:

Can not access headers in extended Express.Request type

问题

我试图扩展Express的Request类型,以确切描述查询的外观。我目前是这样做的:

  1. export interface TypedRequestQuery<T> extends Express.Request {
  2. query: T;
  3. }

这在大部分情况下都可以工作,但有些属性似乎未定义。例如:

  1. (req as TypedRequestQuery<{data: string}>).headers

不起作用。它会产生以下错误:

  1. 属性'headers'在类型'TypedRequestQuery<{ data: string; }>'上不存在

我在多个来源中看到过,Express.Request是请求处理程序的请求参数的正确类型。但也许我理解错了?省略请求处理程序的类型注解确实起作用:

  1. router.get("/", async (req, res) => {
  2. req.headers["x-forwarded-for"] // 没有错误
  3. })

而且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:

  1. export interface TypedRequestQuery&lt;T&gt; extends Express.Request {
  2. query: T;
  3. }

This works for the most part, but some properties do not seem to be defined. For example:

  1. (req as TypedRequestQuery&lt;{data: string}&gt;).headers

Does not work. It results in the following error:

  1. Property &#39;headers&#39; does not exist on type &#39;TypedRequestQuery&lt;{ data: string; }&gt;&#39;

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!:

  1. router.get(&quot;/&quot;, async (req, res) =&gt; {
  2. req.headers[&quot;x-forwarded-for&quot;] // no errors
  3. })

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类型已经允许你定义查询类型...

  1. export interface Request&lt;
  2. P = ParamsDictionary,
  3. ResBody = any,
  4. ReqBody = any,
  5. ReqQuery = ParsedQs, // &#128072;
  6. Locals extends Record&lt;string, any&gt; = Record&lt;string, any&gt;
  7. &gt; ...

查询类型是第四个泛型参数,所以你需要为前三个提供默认值

  1. import { ParamsDictionary, Request } from &quot;express-serve-static-core&quot;;
  2. type TypedRequestQuery&lt;
  3. TQuery,
  4. TParams = ParamsDictionary,
  5. TResBody = any,
  6. TReqBody = any
  7. &gt; = Request&lt;TParams, TResBody, TReqBody, TQuery&gt;;

然后你可以在你的路由中使用它

  1. router.get(&quot;/&quot;, async (req: TypedRequestQuery&lt;{data: string}&gt;, res) =&gt; {
  2. console.log(&quot;headers[x-forwarded-for]:&quot;, req.headers[&quot;x-forwarded-for&quot;]);
  3. console.log(&quot;query[data]:&quot;, req.query.data);
  4. res.send(&quot;我希望Typescript能让我们跳过泛型参数&quot;);
  5. })

你的示例编译失败,因为你尝试使用不兼容的类型覆盖query属性

  1. error TS2430: Interface &#39;TypedRequestQuery&lt;T&gt;&#39; incorrectly extends interface &#39;Request&lt;ParamsDictionary, any, any, ParsedQs, Record&lt;string, any&gt;&gt;&#39;.
  2. Types of property &#39;query&#39; are incompatible.
  3. Type &#39;T&#39; is not assignable to type &#39;ParsedQs&#39;.
  4. interface TypedRequestQuery&lt;T&gt; extends Request {
  5. ~~~~~~~~~~~~~~~~~
  6. interface TypedRequestQuery&lt;T&gt; extends Request {
  7. ~
  8. This type parameter might need an `extends ParsedQs` constraint.

一个兼容的版本需要让你的查询类型扩展ParsedQs

  1. import { Request } from &quot;express-serve-static-core&quot;
  2. import { ParsedQs } from &quot;qs&quot;
  3. interface TypedRequestQuery&lt;T extends ParsedQs&gt; extends Request {
  4. query: T;
  5. }
英文:

Express' Request type already lets you define the query type...

  1. export interface Request&lt;
  2. P = ParamsDictionary,
  3. ResBody = any,
  4. ReqBody = any,
  5. ReqQuery = ParsedQs, // &#128072;
  6. Locals extends Record&lt;string, any&gt; = Record&lt;string, any&gt;
  7. &gt; ...

The query type is the 4th generic so you'd need to provide defaults for the first three

  1. import { ParamsDictionary, Request } from &quot;express-serve-static-core&quot;;
  2. type TypedRequestQuery&lt;
  3. TQuery,
  4. TParams = ParamsDictionary,
  5. TResBody = any,
  6. TReqBody = any
  7. &gt; = Request&lt;TParams, TResBody, TReqBody, TQuery&gt;;

Then you can use it in your routes

  1. router.get(&quot;/&quot;, async (req: TypedRequestQuery&lt;{data: string}&gt;, res) =&gt; {
  2. console.log(&quot;headers[x-forwarded-for]:&quot;, req.headers[&quot;x-forwarded-for&quot;]);
  3. console.log(&quot;query[data]:&quot;, req.query.data);
  4. res.send(&quot;I wish Typescript would let us skip generics&quot;);
  5. })

Your example fails compilation because you're trying to override the query property with an incompatible type

> none
&gt; error TS2430: Interface &#39;TypedRequestQuery&lt;T&gt;&#39; incorrectly extends interface &#39;Request&lt;ParamsDictionary, any, any, ParsedQs, Record&lt;string, any&gt;&gt;&#39;.
&gt; Types of property &#39;query&#39; are incompatible.
&gt; Type &#39;T&#39; is not assignable to type &#39;ParsedQs&#39;.
&gt;
&gt; interface TypedRequestQuery&lt;T&gt; extends Request {
&gt; ~~~~~~~~~~~~~~~~~
&gt;
&gt; interface TypedRequestQuery&lt;T&gt; extends Request {
&gt; ~
&gt; This type parameter might need an `extends ParsedQs` constraint.
&gt;

A compatible version would need to have your query type extend ParsedQs

  1. import { Request } from &quot;express-serve-static-core&quot;;
  2. import { ParsedQs } from &quot;qs&quot;
  3. interface TypedRequestQuery&lt;T extends ParsedQs&gt; extends Request {
  4. query: T;
  5. }

huangapple
  • 本文由 发表于 2023年3月31日 19:13:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/75897888.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定