Skip to main content

How to export Flow definitions in npm packages?

More than 240 000 repositories on GitHub use Flow, but only a few export Flow definitions. In this article, I’ll show you how to export Flow definitions for a module. Before starting, I encourage you to read my previous article about publishing Tree Shaking-friendly packages to npm.

What is Flow?

You’ve probably already seen Gary’s talk from CodeMash 2012 about JavaScript. With Flow in your hands, there should be no more „wat’s”.

Flow is a static type checker for your JavaScript code. It does a lot of work to make you more productive. Making you code faster, smarter, more confidently, and to a bigger scale. – Introduction to type checking with Flow

Flow was first presented at the Scale Conference in 2014 by Facebook. Its main goal was to add additional syntax to JavaScript language to prevent type errors and give developers a more concise idea about bugs that can occur in their code. It also offers a way for IDEs to provide a better environment for spotting errors in real-time.

How to export Flow definitions?

There are currently two ways to export Flow definitions. The easiest one is to include the source files within your package. All you have to do is change their extension to .js.flow and include them with the bundle.

Exporting Flow files

Let’s start by installing the required npm dependencies using the following command:

$ npm install --save-dev glob fs-extra

Once installed, we can write a script that will copy all source files to the /dest directory and change their extension to .js.flow:

// ./scripts/copy-flow-definitions.js
import { basename, resolve } from "path";
import { copy } from "fs-extra";
import glob from "glob";

async function copyFile(file) {
  const srcDir  = resolve(__dirname, "../src");
  const destDir = resolve(__dirname, "../dest");
  const fileDef = `${file}.flow`.replace(srcDir, destDir);

  await copy(file, fileDef);

  console.log(`Copied ${file} to ${fileDef}`);
}

glob(resolve(__dirname, "../src/**/*.js"), (err, files) => {
  files.forEach(file => copyFile(file));
});

Then, you can execute this script at the end of your build pipeline as follows:

{
  "scripts": {
    "build": "npx babel ./src -d ./dest",
    "postbuild": "node ./scripts/copy-flow-definitions.js"
  }
}

Adding definitions to flow-typed

If you plan to version your definitions, you should contribute to the flow-typed repository instead. Flow supports library definitions, which allow you to describe the interface of a module or library separately from the implementation of that module/library.

You can add your definitions by contributing library definitions to the flow-typed repository. It will allow people who use your library to fetch definitions by using the following command:

$ flow-typed install [email protected]

Conclusion

It is important to export Flow definitions so Flow can give errors if someone accidentally misuses your library. Additionally, it integrates well with most IDEs, giving developers a better experience by providing real-time documentation, auto-complete, and pointing mistakes.