Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

extending express request class in Flow

I am building a nodeJS app using Flow, and I need to extend the default express annotation for express$Request to accommodate other fields that I tack on, like .user and .session.

unfortunately, when I try to do this and create middleware that accepts this new Request type, Flow freaks out and I'm not sure what I'm doing wrong.

the original code for express from flow-typed is:

declare class express$Request extends http$IncomingMessage mixins express$RequestResponseBase {
    ....
}

declare type express$Middleware = 
    ((req: express$Request, res: express$Response, next: express$NextFunction) => mixed) |
    ((error: ?Error, req: express$Request, res: express$Response, next: express$NextFunction) => mixed);

so I thought I would just extend express$Request and then all of my middleware should work with the new properties, right?

declare class web$Request extends express$Request {
    user: any,
    isAuthenticated(): boolean,
    session: {
      loginForwardUrl: ?string,
    },
}

const authenticationMiddleware: express$Middleware = (
  req: web$Request, res, next
): mixed => {
  if (req.isAuthenticated()) {
    return next();
  }

  req.session.loginForwardUrl = req.originalUrl;
  return res.redirect('/auth/login/google');
}

unfortunately, this yields the super-complex error:

function
This type is incompatible with
union: function type(s): web/src/index.js:113
Member 1:
function type: flow-typed/npm/express_v4.x.x.js:97
Error:
web$Request: web/src/index.js:114
This type is incompatible with the expected param type of
express$Request: flow-typed/npm/express_v4.x.x.js:97
Member 2:
function type: flow-typed/npm/express_v4.x.x.js:98
Error:
web$Request: web/src/index.js:114
This type is incompatible with an argument type of
null: flow-typed/npm/express_v4.x.x.js:98

can anyone explain what's going on here and how to fix it?

thanks!

like image 958
user358829 Avatar asked Jun 20 '17 23:06

user358829


1 Answers

The error says that an argument/param of type express$Request (Member 1) or null (Member 2) was expected, but web$Request was seen.

Unfortunately, Flow does not support extending/overriding flow/lib types:

https://github.com/facebook/flow/issues/396

What I've begun to do is:

  1. flow-typed install [email protected]
  2. Move express_v4.x.x.js from flow-typed/npm/ to flow-typed/ (outside flow-typed/npm/ so it won't be overwritten by future flow-typed installs, and inside flow-typed/ so flow will automatically make declare blah statements global)
  3. Right below the declare class express$Request... (so it's easy to find and so it's above where it's used inside declare module..., I put:

    declare class express$Request extends express$Request { user: any; isAuthenticated(): boolean; session: { loginForwardUrl: ?string; }; }

I do this instead of putting my custom props on the original class so that it's easy to see which props are custom.

like image 198
Zachary Ryan Smith Avatar answered Oct 23 '22 04:10

Zachary Ryan Smith