Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to import flow annotations, types and interfaces from an npm-published module

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:

  • module A: defines the annotations, types and interfaces
  • module B: relies on module A and wishes to type-check against it, and use its annotations, types and interfaces.

pattern 1

module A

  • 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",
        ...
     },
    
  • publish the module

module B

  • simply declaring the dependency with 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';
    

pattern 2

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

  • publish the module

module B

  • declare the dependency as before with 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 …
  • manually obtain the declarations.js file from the "module-A" package and place it in the decl directory (pointed to from the [libs] section of .flowconfig
  • no need to use any syntax to import types and interfaces; they become automatically available.

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:

  1. which pattern is more idiomatic / advisable ?
  2. is there another pattern ?

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.

like image 944
Marcus Junius Brutus Avatar asked Sep 08 '16 08:09

Marcus Junius Brutus


People also ask

Which function is used to import modules in node js?

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.

Can you use import statements in node?

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.


1 Answers

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

like image 155
ryyppy Avatar answered Oct 22 '22 05:10

ryyppy