Marcus Junius Brutus Marcus Junius Brutus - 2 months ago 31
Node.js Question

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.

Answer

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:

flow@0.32 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

Comments