0

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.

aes
  • 55
  • 1
  • 7

0 Answers0