在Flow中扩展快速请求类

时间:2017-06-20 23:30:30

标签: node.js flowtype flow-typed

我正在使用Flow构建nodeJS应用程序,我需要为express $ Request扩展默认快速注释,以适应我所使用的其他字段,如.user和.session。

不幸的是,当我尝试这样做并创建接受这种新Request类型的中间件时,Flow吓坏了,我不确定我做错了什么。

来自flow-typed的express的原始代码是:

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);

所以我想我会扩展express $ Request然后我的所有中间件都应该使用新属性,对吗?

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');
}

不幸的是,这会产生超复杂的错误:

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

任何人都可以解释这里发生了什么以及如何解决它?

谢谢!

2 个答案:

答案 0 :(得分:4)

错误表示期望express$Request(成员1)或null(成员2)类型的参数/参数,但看到web$Request

不幸的是,Flow不支持扩展/覆盖流/ lib类型:

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

我开始做的是:

  1. flow-typed install express@4.x.x
  2. express_v4.x.x.js从flow-typed / npm /移动到flow-typed /(在flow-typed / npm /之外,所以它不会被未来的流式安装覆盖,并且在flow-typed / so里面flow会自动使declare blah语句全局化)
  3. declare class express$Request...正下方(所以很容易找到它,所以它在declare module...内使用它的上方,我把:

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

  4. 我这样做而不是将我的自定义道具放在原始类上,这样就可以很容易地看到哪些道具是自定义的。

答案 1 :(得分:0)

如果您不想修改原始流程类型/npm/express_v4.x.x.js,则可以使用流程intersection types

import type {$Request} from 'express';

type MyType = {
  foo: string
}:

export type CustomRequest = $Request & {
  foo: MyType | void;
  bar: string | void
};

我喜欢这种方法,因为我可以将自己的类型定义添加到CustomRequest。在typed / npm / express_v4.x.x.js文件中扩展$ Request时,这可能会很棘手。