Reputation: 171
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'.
Setup:
import { Request, Response } from 'express';
function bar(request: Request, response: Response) {
const foo: string = request.query.foo; //marked as error
}
I read on the documentation of Express that you can set a configuration called "query parser" that when set to "simple" will always parse the query parameters as a string
The problem is that Typescript still thinks that something other than string or undefined may come and I can't seem to find a way to override the Request interface, I can only extend it.
Is there any way to override the Request interface? is there something wrong in my approach?
Upvotes: 17
Views: 21828
Reputation: 41
Late to the party and not the best but you can try
const name: string = req.query.name as string;
just fail save the code by null check
Upvotes: 4
Reputation: 1572
Workarounds I ended up using depending on the situation:
1: Example extending the Request type.
import { Request } from 'express';
import { IncomingHttpHeaders } from 'http';
interface iExtendedRequest extends Request {
headers: IncomingHttpHeaders & { authorization: string };
}
// Use the extended request interface as entry param
const getAuth = (req: iExtendedRequest): string => req.headers?.authorization;
2: Example using double casting:
type Users = {
id: number;
name: string;
};
const getUsers = (req: Request) => {
// Cast req.query as unknown
const query = req.query as unknown;
// if allows us to cast it as our type
const user = query as Users;
// and then apply destructuring
const { id, name } = user;
id // number
name // string
};
Upvotes: 0
Reputation: 2076
You could define the types that you will expect on the ReqBody
, ReqQuery
and the other generics of Request type. For the Response
you should also be able to define other types and pass it as generics. Don't forget to install @types/express
by running npm install -D @types/express
Then you could create other SomeHandlerRequest
and others ReqDictionary
, ReqBody
, ReqQuery
and ResBody
for each specific case.
import { Request } from 'express'
// if you need define other response generics
// import { Request, Response } from 'express'
// This types could be exported from other file. Then you should import them
type ReqDictionary = {}
type ReqBody = { foo1 ?: string }
type ReqQuery = { foo2 ?: string }
type ResBody = { foo3 ?: string }
type SomeHandlerRequest = Request<ReqDictionary, ResBody, ReqBody, ReqQuery>
const myCustomHandler = (req: SomeHandlerRequest, res) : void => {
const { foo1 } = req.body
const { foo2 } = req.query
// Your custom logic ..... for example...
if (foo1) {
console.log("foo1 value = ", foo1)
}
if (foo2) {
console.log("foo2 value = ", foo2)
}
res.status(200).json({ foo3 : "it works" })
}
Upvotes: 15
Reputation: 6486
if you're like me, and due to upgrading a dependency, all of a sudden you had lots of errors, you may want a quick fix (until you go through and type all your requests)
so, simply specify the type of req
to any
and you're done. back to the old untyped method.
eg,
router.get('/',(req : any, res, next) => {
const { foo } = req.query;
console.log('foo is a string',foo);
});
Converting an untyped application to a typed one is not a trivial or quick thing. sometimes, you need to upgrade a dependency and get something working again, and have to leave the exercise of adding strict types for another day.
Upvotes: -6