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?
Modifying the query in Express.Request is somewhat more tricky, because Express uses types from express-serve-static-core , which in turn Express doesn’t expose. So the only way to get hold of the proper types is to import { Query } from 'express-static-serve-core'; . The solution is to do:
Look at e.g. typescriptlang.org/docs/handbook/…. Overriding the query type won't change the runtime behaviour (it can't, types and TS don't exist at runtime). The solution is to use generics in the following manner.
I'm trying to use this approach and getting the error: Type 'Request' is not generic. 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".
The Request is a generic which accepts additional definitions: 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> {}
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)
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.
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;
}
The Request
is a generic which accepts additional definitions:
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> {}
Source: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/express/index.d.ts#L112-L117
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
}
In my humble opinion the simpler and straight forward method is to use the StringConstructor
. Any downside of this method in this particular situation is welcome in the comments.
var String: StringConstructor (value?: any) => string Allows manipulation and formatting of text strings and determination and location of substrings within strings.
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With