Flow: .flowconfig should recursively consider other .flowconfig files

Created on 29 Jan 2015  路  14Comments  路  Source: facebook/flow

Example situation: I have a testbed react+flux project. I am managing dependencies with npm. My build system is gulp, and I am trying to integrate gulp-flowtype.

In package.json:

  "dependencies": {
    "react": "latest"
  },
  "devDependencies": {
    "gulp": "^3.8.10",
    "gulp-flowtype": "latest"
  }

It happens that gulp-flowtype includes a test file gulp-flowtype/test/main.js that opts in to flow with the /* @flow */ pragma. gulp-flowtype's .flowconfig specifies:

[ignore]
.*/node_modules/*
.*/test/*
[include]

but when I run flow check from my project's root directory, flow digs into my_project/node_modules and attempts to type-check my_project/node_modules/gulp-flowtype/test/main.js. This behavior seems wrong -- if an npm package declares that certain assets shouldn't be typechecked, then packages depending on it should also obey that declaration.

feature request

Most helpful comment

We've been talking about this more recently and it does seem like considering other .flowconfigs is a good idea

All 14 comments

So a package owner can decide which files should and shouldn't be typechecked by adding or removing the @flow at the top of the file, so there is a way to do that. However I'm not sure if it's a good idea for the options in foo/bar/.flowconfig to be automatically used in foo/.flowconfig.

The primary purpose for the .flowconfig file in a directory foo/bar is to indicate that foo/bar is a root directory for Flow. So when you run flow in foo/bar or in one of it's child directories, Flow will find foo/bar/.flowconfig, watch it's child directories, and use the options in foo/bar/.flowconfig. It's not intended to be part of a recursive configuration, in the way that .gitignore is, and it would be problematic to use it as such, because there are side effects of it's existence beyond the configuration it provides.

Also, it's somewhat common for a single repository to contain multiple overlapping roots. These convoluted setups make recursive configuration a little tricky. Furthermore, I think each root needs full control over what is being included and excluded. I'm not sure if they can afford to delegate to a config file in a subdirectory.

Thank you for reporting this issue and appreciate your patience. We've notified the core team for an update on this issue. We're looking for a response within the next 30 days or the issue may be closed.

We've been talking about this more recently and it does seem like considering other .flowconfigs is a good idea

Any updates here @gabelevi?

Naively (with no knowledge of Flow internals 馃槄), I would expect Flow to use the "nearest" .flowconfig (and corresponding flow-typed definitions) for each file. E.g.

my-project/
  .flowconfig
  flow-typed/
  src/
    main.js
  node_modules/
    useful-library/
      .flowconfig
      index.js

The inner project shouldn't be affected by the outer project's .flowconfig or flow-typed definitions.

The current behavior seems broken to me. It breaks the encapsulation of dependencies鈥攊t makes their implementation details matter to the caller. This is in contrast to other "correctness tools": e.g. I don't have to care how my dependencies use ESLint or run their test suites.

Additionally, this would be great for putting into a test directory to define mocha/jasmine globals like describe, it, etc., without polluting global types.

I have a similar issue in a project with multiple modules. For one of the modules I needed to enable module.ignore_non_literal_requires=true, but when flow would check the module from the root, that option would get ignored, causing my project to throw errors.

My "workaround" was to ignore that module from the root, but now I have to run flow inside that module to get it to typecheck. This isn't a big deal in my situation because atom's linter-flow package runs local to each file and shows correct errors from any file, but it also requires me to copy any options from the root config to the module-specific one which is a bit of an annoyance.

To add my use cases:

  • Tests need different config. than source files
  • Including a Flow-enabled project in another

Initially I did not use Flow for tests because my (mocha) tests use the "compiled" files and not the source files. I also didn't want to compile test files too.

However, I discovered that even if I don't have any Flow annotations in the test files, simply by including them in the overall Flow parsing a lot more code paths are checked.

So I enabled Flow for the test files - but I ended up seeing every error twice!

First I see the error on the source file, but now I also see the (same) error from the compiled files used by the tests.

I would like to solve this over-reporting by adding a .flowconfig to he source files that excludes the compiled files directory, and the opposite configuration for the test directory.


I also see problems when I include my Flow-enabled library under node_modules of another (also Flow enabled) project. I end up seeing errors internal to the included project. What's the use of that, in general? You can't really do anything about code in an included package. So unless it's in a path actually used by the current project (in my case, the errors are in files not used by anything so they could be completely ignored) this is just confusing, to see errors for somebody else's stuff that you don't even use (the particular files with the errors).

I think this issue is a subset of a more general problem: Support for multiproject repositories

In my case I have a monorepo with multiple projects. As time goes by, some of the sub projects will be mature into their own independent package. Obviously I had the same concern as the OP, and most likely people with my same problem will find this issue.

Is there any good documentation on how to setup Flow for multiproject repositories?

Basically, what @fgarcia succinctly pointed out. I too have a big monorepository that branches off into multiple projects, each having it's own Yarn workspace, with differing build tools, ways modules are resolved, etc.

Another case here :

Single project with both Jest and Testcafe test fixtures.

Both define a global test() function. Testcafe is winning (is this because it's flow-typed lib loads after jest and squashes it's globals?), so marking any of the Jest test fixtures with // @flow makes them fail checks because test() in Testcafe always expects you to pass an async function with a fixed parameter.

Workaround (other than taking off // @flow) : in Jest test() is an alias of it() and this is reflected in the libdef, so you can switch to it() in your Jest tests.

This isn't ideal though - Jest's documentation encourages you to use test() from the start so most suites written for Jest will use test() and not it() by default.

Any updates here?

I'd really like this as well. I like importing from absolute paths within modules, but can't use it within monorepo packages because they all need to point to different places.

This would be great. I'd also like to be able to use it in monorepos.

For reference/easier findability, these are the flowconfig related issues/suggestions I found that would bring it in line with other tools like eslint, babel, webpack, etc:

Was this page helpful?
0 / 5 - 0 ratings