I have verified through testing that two patterns are possible for importing flow annotations, types and interfaces from an npm-published module.
In what follows I 'm using the below module names:
use the export type
syntax for both types and interfaces:
type IComplex ...
interface IMutableComplex ...
export type {IComplex, IMutableComplex}
copy all *.js
files as *.js.flow
. E.g. by having something like the following in package.json
:
"main": "lib/index.js",
"scripts": {
"prepublish": "mkdir -p lib && for f in $(find src/ -iname *.js | cut -c5-) ; do cp src/$f lib/$f.flow; done",
...
},
npm i --S module-A
makes the annotations available as well because of the js.flow
files in the lib/
directory of the published module.import both types and interfaces with the following syntax:
import type {IComplex, IMutableComplex} from 'module-A';
define types, interfaces and module in a declarations.js
file placed in the decl
directory (pointed to from the [libs]
section of .flowconfig
):
type IComplex = { ...
interface IMutableComplex { ...
declare module "module-A" {
declare function foo(i: number): number;
}
no need to copy *.js
files as *.js.flow
in the prepublish
script
npm i --S module-A
. However this time, no annotations, types and interfaces are available as "module-A" does not include any *.js.flow
files, so …declarations.js
file from the "module-A" package and place it in the decl
directory (pointed to from the [libs]
section of .flowconfig
The above two patterns are the only methods I have discovered and have verified that they work (though I could find no comprehensive write-up).
My questions are:
Regarding question #1 I can see that "pattern 2" is the only possible method if "module-A" is published by another organization / person. Otherwise if one publishes both modules I think "pattern 1" is more straightforward.
In order to use Node. js core or NPM modules, you first need to import it using require() function as shown below. var module = require('module_name'); As per above syntax, specify the module name in the require() function.
You may or may not want to use the “import” statement in your Node. js project, but if your job requires you to use “import” instead of “require” then you can use the above-specified methods. The whole concept behind using the “import” statement instead of “require” in Node.
You are absolutely right with your observations. These are the two methods to publish your flowtype definitions. There is no other way to do it, or better: The official migration plans will kinda go in both directions, because for now, it is impossible to force all JS projects to adapt flow.
Right now, "pattern 2" describes what we call 'libdef' files or 'declaration files'. With the flow-typed
project, we try to vendor high-quality libdef files for common third-party node modules.
Both patterns have their up- and downsides... the biggest problem with vendoring *.flow.js
files is, that they assume a specific version of flow (e.g. peerDependency flow-bin doesn't understand your newest used syntax). On the other hand it is a leaner way to keep the types synced up with the actual codebase.
Anyways, both ways are valid, just make sure your consumers are not forced to change their flow
version just for your package.
Some another useful information:
[email protected]
introduces an experimental new feature called flow gen-flow-files
, which will create your *.flow.js
in a more efficient manner by just copying type information instead the whole code.
Also, I created an issue on flow-typed which starts the exact same discussion right here: https://github.com/flowtype/flow-typed/issues/286
Cheers
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With