How to type `request.query` in express using TypeScript?

问题描述 投票:0回答:9

我正在使用 TypeScript 运行一个

express.js
应用程序。 每次我尝试处理
request.query.foo
我都会收到以下错误:

Argument of type 'string | ParsedQs | string[] | ParsedQs[] | undefined' is not assignable to parameter of type 'string'.
  Type 'undefined' is not assignable to type 'string'.

设置:

import { Request, Response, Router } from 'express';

const router = Router();

function getHandler(request: Request, response: Response) {
  const { query } = request;

  query.foo; // string | QueryString.ParsedQs | string[] | QueryString.ParsedQs[] | undefined

}

router.route('/')
  .get(getHandler)

有没有正确的方法来键入

request.query
而无需转换?

typescript express url types request
9个回答
38
投票

解决方案是通过以下方式使用泛型。

const router = Router();

interface Foo {
    foo: string;
}

function getHandler(request: Request<{}, {}, {}, Foo>, response: Response) {
  const { query } = request;

  query.foo;

}

router.route('/')
  .get(getHandler)

13
投票

定义

Request
是一个泛型,它接受额外的定义:

interface Request<
  P = core.ParamsDictionary,
  ResBody = any,
  ReqBody = any,
  ReqQuery = core.Query,
  Locals extends Record<string, any> = Record<string, any>
> extends core.Request<P, ResBody, ReqBody, ReqQuery, Locals> {}

来源:https://github.com/DefinitelyTyped/DefinitelyTyped/blob/89a4f41af507e68daf5f4794ad257f48920275f2/types/express/index.d.ts#L113-L118

例子

interface RequestParams {}

interface ResponseBody {}

interface RequestBody {}

interface RequestQuery {
  foo: string;
}

function getHandler(
  request: Request<RequestParams, ResponseBody, RequestBody, RequestQuery>,
  response: Response
) {
  const { query } = request;

  query.foo; // string
}

7
投票

我喜欢在我的项目中使用以下方法。

  const { url } = req.query;
  
  if (typeof url !== "string") {
    throw new ServerError("Query param 'url' has to be of type string", 400);
  }

在检查类型之后,TypeScript 不会再抱怨这个范围了。


6
投票

你可以这样做:-

interface Query {
   param1:string;
   param2:string;
};

function getHandler(request: Request, response: Response) {
   const {param1,param2} = request.query as unknown as Query;
}

1
投票

在我看来,更简单直接的方法是使用

StringConstructor
。欢迎在评论中提出这种方法在这种特殊情况下的任何缺点。

var 字符串:StringConstructor (价值?:任何)=>字符串 允许对文本字符串进行操作和格式化,以及确定和定位字符串中的子字符串。

import { Request, Response, Router } from 'express';

const router = Router();

function getHandler(request: Request, response: Response) {
  const { foo } = request.query;

  String(foo) // string
}

router.route('/').get(getHandler)

0
投票

另一种可能的解决方案是使用Type Assertion

function getHandler(request: Request, response: Response) {

  const foo: string = request.query.foo as string

  //do something with foo ...

}

0
投票

对我来说最好的解决方案是首先转换为未知,然后是我的自定义界面。

interface CustomReqQuery {
   foo: string;
   bar: string;
}

function getHandler(req: Request, res: Response) {
  const { foo, bar } = req.query as unknown as CustomReqQuery;

  ...
}

0
投票

您应该使用实际的 JS 验证您的传入数据,而不是欺骗打字稿。

如果您只对处理

foo
是一个字符串感兴趣,那么在您从
query
中提取它时验证它是一个字符串。

function getHandler(request: Request, response: Response) {
    const { query } = request;

    const foo = (typeof query.foo === "string") ? query.foo : "";

    // Want to error check?
    if (foo === "") {
        // Handle missing foo
    }

    // You now have a guaranteed string that typescript recognizes as a string

    const myNumber = parseInt(foo); // No warnings here
}

0
投票

只是一个想法:

import { Request, Response, Router } from 'express';

const router = Router();

interface HandlerRequest extends Request {
    query: {
        foo: string
    }
}

function getHandler(request: HandlerRequest, response: Response) {
  const {query: {foo}} = request;

  if (foo) {
    // Do something
  } else {
    // Otherwise...
  }       
}

router.route('/')
  .get(getHandler)
© www.soinside.com 2019 - 2024. All rights reserved.