Referencing the answers on How to annotate Express middlewares with JSDoc?, there are answers on how to add types to express methods with JSDoc. They all generally give a way to type your handlers with @param
and optionally extend the express.Request
and express.Response
interfaces.
Express methods are defined using an IRouterMatcher
type you can see defined here. The type parameters of IRouterMatcher
are used in the handlers
that get passed to instances of it so that all your handlers use the same ResBody
, ReqBody
types, etc.
In cases where there is a single handler, of course, this is not a problem.
In cases where there are multiple handlers, you can see the types being enforced.
api.get(
"/person",
(req: express.Request<{}, { name: string, age: number }>, res) => {
res.send({ name: "joe", age: 5 });
},
(req, res) => {
// ts(2345) error at 'color'
res.send({ name: "joe", color: "red" });
});
In a syntax using generic type parameters I like more
api.get<{id: number}, { name: string, age: number }>(
"/person",
(req, res) => {
res.send({ name: "joe", age: 5 });
},
(req, res) => {
// ts(2345) error at 'color'
res.send({ name: "joe", color: "red" });
});
In JavaScript using JSDoc with ts-check, I can get the same error on all handlers if I annotate both req
and res
(ResBody
is defined on both) on at least one of them.
api.get("/person",
/**
* @param {express.Request<{}, { name: string, age: number }>} req
* @param {express.Response<{ name: string, age: number }>} res
*/
(req, res) => {
res.send({ name: "joe", age: 5 });
},
(req, res) => {
// ts(2345) error at 'color'
res.send({ name: "joe", color: "red" });
});
However, this is annoying duplication and if I take away type information from either req
or res
then the type checking goes away - so I have to have both. Ideally, it would be nice to supply generic types to IRouterMatcher
(get
, post
, etc.,) and have them enforced top-down like the second TypeScript example above but instead using JSDoc, but it seems passing generic types to methods is not possible in JSDoc (?).
This seems like a problem begging for a workaround. I'm hoping passing generic types is something you can do in JSDoc, but given the GitHub issue on the TS repo linked in the post above has been open since 2018, I don't have high hopes. I'm thinking there has to be a workaround though, but nothing I've tried has worked so far.