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

10,571

Solution 1

The solution is to use generics in the following manner.

const router = Router();

interface Foo {
    foo: string;
}

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

  query.foo;

}

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

Solution 2

you can do it like this :-

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

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

Solution 3

I like to use the following approach in my projects.

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

After checking the type TypeScript won't complain any more for this scope.

Share:
10,571
marcobiedermann
Author by

marcobiedermann

Full-Stack JavaScript Engineer with focus on React, Redux &amp; Node.js and passioned about Open Source working @Mobimeo based in Berlin, Germany

Updated on June 20, 2022

Comments

  • marcobiedermann
    marcobiedermann about 2 years

    I'm running an express.js application using TypeScript. Every time I try to process request.query.foo I get the following error:

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

    Setup:

    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)
    

    Is there a proper way to type request.query without casting?

  • tim.rohrer
    tim.rohrer over 3 years
    Have you tested this? I'm trying to use this approach and getting the error: Type 'Request' is not generic.
  • Hongbo Miao
    Hongbo Miao over 3 years
    Tested on @types/express 4.17.11. Works great! BTW, it would be better to use Request<unknown, unknown, unknown, Foo>. Otherwise, the ESLint will give error: Don't use {} as a type. {} actually means "any non-nullish value".
  • Silviu Burcea
    Silviu Burcea almost 3 years
    Or const getHandler: RequestHandler<unknown, unknown, unknown, Foo> = (req, res) => { ... }
  • tim.rohrer
    tim.rohrer almost 3 years
    For anyone else who reads my comment and wonders...it turns out I had not imported Request from the Express types, and so Fetch type of Request was being used.
  • marcobiedermann
    marcobiedermann almost 3 years
    Yeah, I know, but I would like to avoid type casting
  • DaDo
    DaDo almost 3 years
    This only works for the query object. How would I do this for the params and body objects?
  • tim.rohrer
    tim.rohrer over 2 years
    Similar to @HongboMiao, I arrived at a similar ESLint complaint, but believe that instead of using unknown for each, wouldn't Record<string, unknown> be better as these should always be objects, right?
  • s27840
    s27840 over 2 years
    If you get Type 'Request' is not generic. add import type { Request } from "express";
  • Todd Rylaarsdam
    Todd Rylaarsdam about 2 years
    This is a good approach. Handles types well, and is nice and simple
  • oyalhi
    oyalhi about 2 years
    it's a good practice to make params such as foo?: string optional, since they may not be present.