0

I'm trying to come up with an answer to How to type `request.query` in express using TypeScript? because I want one, myself.

In express, using string literal types the route parameters get inferred correctly. However, express has no way of specifying a strong type for its query string parameters without specifying the route template parameters directly, which means specifying all of them.

The RouteMatcher's declaration is:

export interface IRouterMatcher<
    T,
    Method extends 'all' | 'get' | 'post' | 'put' | 'delete' | 'patch' | 'options' | 'head' = any
> {
    <
        Route extends string,
        P = RouteParameters<Route>,
        ResBody = any,
        ReqBody = any,
        ReqQuery = ParsedQs,
        Locals extends Record<string, any> = Record<string, any>
    >(
        // tslint:disable-next-line no-unnecessary-generics (it's used as the default type parameter for P)
        path: Route,
        // tslint:disable-next-line no-unnecessary-generics (This generic is meant to be passed explicitly.)
        ...handlers: Array<RequestHandler<P, ResBody, ReqBody, ReqQuery, Locals>>
    ): T;
    //...
}

I would like to create an identity wrapper function, withQS, that will let me specify the ReqQuery parameter alone and infer the remaining template types.

const withQS = <
  ReqQuery extends QueryString.ParsedQS,
  /* TODO */
>(path: /* TODO */, ...handlers: /* TODO */): /* TODO */ =>
  [ path, ...handlers ];

app.get(...withQs<{ foo: 'bar' | 'baz' }>(
  ('some/:route/:param', (req, res, next) => {
    const { foo } = req.query;
    // knows foo is 'bar' or 'baz'
    const { route, param } = req.params;
    // knows that route and param are the only properties
  }
);

An alternative would be to have withQS wrap each handler, but that's less desirable.

Ideas? TS Playground

4
  • Since this isn't tagged with express I assume we shouldn't need dependencies on it to answer the question. If so, please provide a minimal reproducible example that clearly demonstrates the issue you are facing. Ideally someone could drop the code into a standalone IDE like The TypeScript Playground (link here!) and immediately get to work solving the problem without first needing to re-create it. So there should be no pseudocode, typos, unrelated errors, or undeclared types or values. If not, maybe we should put the express tag on it? Commented Dec 18, 2021 at 20:09
  • Nah, this is purely a TS question. When I have time (tomorrow evening likely), I'll throw together a TS Playground and let you know when I have. I typed this all out on my phone, or I would have done so already. Commented Dec 19, 2021 at 1:32
  • @jcalz Done! Hopefully it's minimal enough. Commented Dec 19, 2021 at 17:56
  • Are you asking about partial type parameter inference as requested in ms/TS#26242? If so then you need a workaround like currying (see this approach). If not then could you elaborate more? Commented Dec 19, 2021 at 22:16

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.