Howdy. I'm sorry if this issue already exists. This more question than issue report.
My project frequently uses moment, underscore, React etc, so my team decided to carry out this modules in webpack config to ProvidePlugin, that makes them global variables.
webpack.config.js: {...,
plugins: [
new webpack.ProvidePlugin({
'React': 'react',
'_': 'underscore',
}),
], ...}
Now, when i tried to connect flow, it of course could not resolve their names.
After reading documentation, i tried to create flow-typed/customLibDef.js like that
import underscore from 'underscore';
declare var _: typeof underscore;
declare var moment: Class<moment$Moment>;
And it works for moment, but not for _: it typed as 'any'.
Same goes for React and PropTypes modules: connecting them by plugin and not importing them explicitly in my code will throw a flow error.
So i ask: is there any way to let flow know about this globals without importing them everywhere they are needed? A way to declare modules globally?
For all vendor libs it's better to use definitions which are simplified version of code with only types of exported api.
Definitions can be found here and installed manually or using flow-typed cli
https://github.com/flowtype/flow-typed
I already connected flow-typed, but it solves different problem. I need to let flow know about this globally accessed modules (_, moment, React, etc), but as i understand you can't import types in library definitions => can not write libdef like this
import type Underscore from 'underscore';
declare var _: Underscore;
Why not just use explicit import which resolves to global variable? Globals in your code are always implicit hell, with types or without them.
@showmeyourhits Try adding the pre-existing libdef for underscore in your flow-typed folder from https://github.com/flowtype/flow-typed/ then add this line to your customLibDef.js
declare var _: Underscore;
@dahliasalem This marks_ as any type, which makes flow useless. I don't know, why this works for moment, and not for _
@showmeyourhits Hmm I am not really sure how that declares it as type "any" since flow supports class types
https://flow.org/en/docs/types/classes/
We're having this exact same use-case with Webpack ProvidePlugin. At the bare minimum all we'd need is a way to tell Flow (for example a [globals] in .flowconfig) that "_these libraries are globally imported; treat them as any / don't assume they're undefined_". For the moment we have 12 of these global libraries provided by Webpack, and it saves us quite a few lines of code by not having to manually import them absolutely everywhere.
We're not looking for a flow-typed -level of fidelity here; just a simple way of ignoring / type-stubbing global libraries.
@neutraali create manually a file with types for your global vars.
For example, you can create flow-typed/globals.js
And decare your vars there like this:
declare var myGlobalVar: MyGlobalVarType;
create manually a file with types for your global vars
The implicit assumption here is that I'm going to need to import this file in every Flow -file?
... Which is better than nothing, but still a bit clunky considering this feels like it should be handled via .flowconfig.
The implicit assumption here is that I'm going to need to import this file in every Flow -file?
No)
Right, so I looked it up and made a "global definition file" at lib/Flow.js. I then added this path to .flowconfig under [libs]. Seems to be working perfectly! Thanks to @apsavin for the pointers.
The next thing I'll have to worry about are Webpack _alias paths_, e.g. custom-path/lib/Example.js, but having those global module definitions is a huge enough deal already. :smile_cat:
Webpack alias paths
@neutraali Try something like this:
.flowconfig
module.name_mapper='assets\.json$' -> '<PROJECT_ROOT>/src/sj/types/common/assetsModule.js'
assetsModule.js
// @flow
declare module.exports: {
vendor: {
js: string,
},
client: {
js: string,
},
};
Hey thanks again @apsavin - Ended up not needing a library definition for that, I just used the module.name_mapper + regex, like so (.flowconfig):
[options]
module.name_mapper='^custom-alias\/\(.*\)' -> '<PROJECT_ROOT>\/\1'
module.name_mapper='^another-custom-alias\/\(.*\)' -> '<PROJECT_ROOT>\/lib/custom-library/src/\1'
. . .
... Works beautifully :smile_cat: