GithubHelp home page GithubHelp logo

facebook / flow Goto Github PK

View Code? Open in Web Editor NEW
22.1K 391.0 1.8K 130.49 MB

Adds static typing to JavaScript to improve developer productivity and code quality.

Home Page: https://flow.org/

License: MIT License

Shell 1.84% JavaScript 27.30% OCaml 69.71% C 0.80% Makefile 0.06% Ruby 0.01% Python 0.02% C++ 0.04% Dockerfile 0.03% PowerShell 0.01% CSS 0.17% Vim Snippet 0.01%

flow's Introduction

Flow

CircleCI Follow @flowtype MIT License GitHub contributors GitHub top language Join Discord Chat

Flow is a static typechecker for JavaScript. To find out more about Flow, check out flow.org.

Contents

Requirements

Flow works with:

  • macOS (x86_64)
  • Linux (x86_64 and arm64)
  • Windows (x86_64, Windows 10 recommended)

There are binary distributions for each of these platforms and you can also build it from source on any of them as well.

Using Flow

Check out the installation instructions, and then the usage docs.

Using Flow's parser from JavaScript

While Flow is written in OCaml, its parser is available as a compiled-to-JavaScript module published to npm, named flow-parser. Most end users of Flow will not need to use this parser directly, but JavaScript packages which make use of parsing Flow-typed JavaScript can use this to generate Flow's syntax tree with annotated types attached.

Building Flow from source

Flow is written in OCaml (OCaml 4.14.0 is required).

  1. Install system dependencies:

    • Mac: brew install opam

    • Debian: sudo apt-get install opam

    • Other Linux: see opam docs

    • Windows: cygwin and a number of dependencies like make, gcc and g++ are required.

      One way to install everything is to install Chocolatey and then run .\scripts\windows\install_deps.ps1 and .\scripts\windows\install_opam.ps1. Otherwise, see the "Manual Installation" section of OCaml for Windows docs and install all of the packages listed in our install_deps.ps1.

      The remainder of these instructions should be run inside the Cygwin shell: C:\tools\cygwin\Cygwin. Then cd /cygdrive/c/Users/you/path/to/checkout.

  2. Validate the opam version is 2.x.x:

    opam --version

    The following instructions expect 2.x.x. Should your package manager have installed a 1.x.x version, please refer to the opam docs to install a newer version manually.

  3. Initialize opam:

    # on Mac and Linux:
    opam init
    
    # on Windows:
    scripts/windows/init_opam.sh
  4. Install Flow's OCaml dependencies:

    # from within this git checkout
    make deps

    note: If you find that you get an error looking for ocaml-base-compiler version, your local dependency repo may be out of date and you need to run opam update + opam upgrade

  5. Build the flow binary:

    eval $(opam env)
    make

    This produces the bin/flow binary.

  6. Build flow.js (optional):

    opam install -y js_of_ocaml.5.5.2
    make js

    This produces bin/flow.js.

    The Flow parser can also be compiled to JavaScript. Read how here.

Running the tests

To run the tests, first compile flow using make. Then run bash ./runtests.sh bin/flow

There is a make test target that compiles and runs tests.

To run a subset of the tests you can pass a second argument to the runtests.sh file.

For example: bash runtests.sh bin/flow class | grep -v 'SKIP'

Join the Flow community

License

Flow is MIT-licensed (LICENSE). The website and documentation are licensed under the Creative Commons Attribution 4.0 license (website/LICENSE-DOCUMENTATION).

flow's People

Contributors

alexchow avatar andrewjkennedy avatar avikchaudhuri avatar ballardrog avatar bhosmer avatar dabek avatar darichey avatar dependabot[bot] avatar dlreeves avatar dsainati1 avatar dsereni avatar evanyeung avatar gabelevi avatar gkz avatar goodmind avatar int3 avatar jbrown215 avatar jeffmo avatar ljw1004 avatar mroch avatar msullivan avatar mvitousek avatar nmote avatar oulgen avatar pakoito avatar panagosg7 avatar pieterv avatar samchou19815 avatar samwgoldman avatar vjeux avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

flow's Issues

relationship with JSDoc?

It would be great if the readme or wiki states the differences/similarities between JSDoc (or any other tools) and flow. Thanks

Checking `!== undefined` should suffice for an optional argument

This code doesn't type-check:

/* @flow */

function foo(x?: string): string {
    if (x !== undefined) {
        return x;
    }
    return "meow";
}

Changing the conditional to x != null makes the code work, but I believe checking against undefined should suffice because the argument type itself isn't nullable. Also: != undefined doesn't work even though it has the same meaning as != null.

Add dom definition for canvas

document.createElement('canvas') returns a type HTMLElement, which does not define methods like "getContext". There should be a HTMLCanvasElement in dom.js similarly to HTMLImageElement.

Usage with shims

Currently we rely quite heavily on shimming external dependencies for usage on our client side applications. This means that our require calls are sometimes to packages which are not available through package.json, and also may not have an entry point for CommonJS - flow cannot find the required modules.

A common package.json looks like this:

{
    "name": "package",
    "version": "0.0.0",
    "devDependencies": {
        "grunt": "~0.4.5",
        "grunt-bless": "~0.1",
        "grunt-contrib-copy": "~0.5.0",
        "grunt-contrib-cssmin": "~0.9.0",
        "grunt-contrib-clean": "~0.4.0",
        "grunt-contrib-watch": "~0.6.0",
        "grunt-contrib-jshint": "~0.9.0",
        "grunt-contrib-requirejs": "~0.4.0",
        "grunt-contrib-concat": "~0.3.0",
        "grunt-contrib-uglify": "~0.2.0",
        "grunt-contrib-less": "~0.11",
        "matchdep": "~0.1.2",
        "json5": "~0.2.0",
        "grunt-react": "~0.7.0",
        "grunt-browserify": "~3.1",
        "browserify-shim": "~3.8",
        "envify": "~0.2.0",
        "bootstrap": "3.2.0",
        "font-awesome": "4.2.0",
        "grunt-svgstore": "^0.3.3",
        "jquery": "~2.1",
        "parsleyjs": "~2.0"
    },
    "browser": {
        "entwine": "./source/lib/entwine/jquery.entwine-dist.js",
        "jquery": "./node_modules/jquery/dist/jquery.js",
        "modernizr": "./source/js/src/modernizr.js",
        "bootstrap": "./source/lib/bootstrap/bootstrap.js",
        "waypoints": "./source/lib/waypoints/waypoints.js",
        "selectfield": "./source/lib/jquery/jquery-ui-select/jquery-ui-select.js",
        "datepicker": "./source/lib/jquery/jquery-ui-datepicker/jquery-ui-datepicker.js",
        "autotab": "./source/lib/autotab/jquery.autotab.min.js",
        "chosen": "./source/lib/chosen/chosen.jquery.js"
    },
    "browserify": {
        "transform": [
            "browserify-shim"
        ]
    },
    "browserify-shim": {
        "jquery": {
            "exports": "$"
        },
        "entwine": {
            "exports": null,
            "depends": [ "jquery" ]
        },
        "modernizr": {
            "exports": "Modernizr"
        },
        "bootstrap": {
            "exports": "bootstrap"
        },
        "waypoints": {
            "exports": null
        },
        "selectfield": {
            "exports": null
        },
        "datepicker": {
            "exports": null
        },
        "autotab": {
            "exports": null
        },
        "chosen": {
            "exports": null
        }
    }
}

It would be great if there was a way to shim dependencies similar to how browserify does this, so that we can run flow on our codebase. Alternatively if there is a way to type hint that we don't want certain dependencies included that would probably also work 😄

Standard streams support

As Flow is command line tool, does he support standard input and output streams?

Reading the docs I guess I'm not able to do something like

cat lib.js | flow check

Support predicate types

Currently, if you do

if (typeof x === "function") {
  // ...
}

then Flow knows that the code within the if statement is a function. This doesn't work if you instead call a helper function like Underscore's _.isFunction. Similarly, utilities like Object.assign and React.PropTypes seem to have hardcoded behavior at the AST level, so they don't work when aliased or given alternative names.

Will it be possible to teach Flow about these sorts of functions so that it's possible to use these third-party libraries without changing code too much?

Support for ES6 features

I didn't see an existing issue for this, nor do I see anything on the website about it, but I'm sure you all have plans for this. Looks like there are several ES6 features this doesn't support yet, particularly let:

let x = 5;
/Users/james/projects/mozilla/gecko-dev/toolkit/devtools/server/actors/foo.js:3:1,10: 
Unsupported variable declaration: let

/Users/james/projects/mozilla/gecko-dev/toolkit/devtools/server/actors/foo.js:3:5,5: var x
Unknown global name

I'm interested in using this as a "light" type checker in Firefox. I don't know if we'll ever start adding a lot of type declarations, but this looks like it could be a nice "linter" using the weak mode. (still not sure how far that goes yet, but if it can even catch a few things that would be cool).

Since we can code against SpiderMonkey, we use ES6 a lot, like:

  • let/const
  • for-of
  • short-hand object syntax ({ foo } turns into { foo: foo })
  • generators

That's just off the top of my head. On the file I tried, the main things I hit were let/const and for-of.

Support require which returns `any` if flow lost it

I want to ignore Required module not found and load it as any.
Type checking to extenal libraries are not serious problem.

I tried this

declare require: (s: string) => any;

but it overrides all require and lost other info.

Add ability to import/export type definitions

This was discussed this briefly in IRC (log), and it seems like it'll require some new syntax, likely something to the effect of:

import type { MyType } from "./SomeModule";

This can be easily compiled out of the final output, and use the same path resolution as a regular module import would. The syntax might be a bit confusing when part of a CommonJS module, but on the plus side it has parity with ES6 module syntax.

Rather than add new export syntax, it should be okay to implicitly export all the types in a file (since you have to specify which exactly ones you're importing anyways).

Export type signature without exporting the class itself

Is there a way to export a type signature without exporting the constructor? For example, in one project I have, we have a Style class where the constructor isn't exposed, just certain instances:

https://github.com/Khan/KaTeX/blob/a2f81d9d73940842085f73fa626b3ef008f68062/src/Style.js

Right now I can write something like:

var Style = require("./Style");
type StyleType = typeof Style.DISPLAY;

var s: StyleType = ...;

but it would be nice if there was a way to export a type directly from a module, so that perhaps I could write var s: Style.T; or something like that.

Support optional properties in objects

If I have the following type:

type MyType = {
  a: ?any;
  b: ?any;
}

And the following instance of it:

var myThing : MyType = {
  a: 'hello'
};

Flow will find the following error:

/Users/tboyt/Coding/mode7/src/Foo.js:2:15,5:1: property b
Property not found in
  /Users/tboyt/Coding/mode7/src/Foo.js:7:24,9:1: object literal

This makes sense, given that the maybe type is intended to be either the given type or null, not the type or undefined. However, not being able to define a property as entirely optional - e.g., being either a specific type or undefined - seems like a big missing feature.

For an example use case, imagine an API with a constructor that uses a hash of keyword arguments, most of which are optional. It would be great to be able to enforce the types of those arguments, if present, using Flow, and ignore missing arguments.

function overloading

I would like to express a function with the following overloading:

<B>(func: () => B): () => Promise<B>;
<A,B>(func: (a:A) => B): (a: A) => Promise<B>;

it seems to me that it is not possible since :

<A,B>(func: () => B | (a:A) => B): () => Promise<B> |  (a: A) => Promise<B>;

Does not conditionally constraint the return type, any idea ?

Mention flow init when doesn't find .flowconfig

This would be nice to make this error message more explicit as to what you need to do to fix

"I don't have any idea why flow makes an error message 'Could not find a .flowconfig in . or any of its parent directories'"

Parse error with type annotation in fat-arrow

The parser does not parse type annotation on argument in fat-arrow:

/*@flow*/
var f = (t: string) => t;
***/sampleArrow.js:2:11,11: Unexpected token :

It also does not parse return value type annotation:

/*@flow*/
var f = (t): string => t;
***/sampleArrow.js:2:12,12: Unexpected token :

When errors are found a non-zero status code should be returned

I'm trying to integrate flow into travis ci for continuous integration, but flow always returns a 0 status code even when errors are found. To make it more compatible with CI, the tool should return a non-zero status code (or have something to make it more compatible).

Add a way to export class types without using ES6 class syntax

It doesn't seem possible to declare classes by writing out the constructor and prototype manually that Flow will properly recognize, along the lines of

function Foo(x: number) {
  this.x = x;
}
Foo.prototype.squared = function(): number {
  return this.x * this.x;
}

Is this off the table completely or is there a way that Flow can be made to recognize this sort of declaration?

Global variables

Maybe this has been asked already or it's not working for me, but I keep getting these errors:

/client/components/App.js:12:19,24: identifier Meteor
Unknown global name

How can i make Meteor global?

I have done flow start --lib ./lib which contains a file meteor.js that has declare var Meteor: any but it doesn't seem to work.

Support for immutability checks

When I write JavaScript code, I try to treat objects and arrays as immutable, and I prefer writing pure functions whenever possible. I find this makes code much easier to reason about and avoids lots of subtle bugs. (I learned about the practical benefits of immutable collections from Clojure.)

So it would be nice if Flow could have some sort of immutability checking. With a "const" annotation, the programmer could:

  1. Annotate a variable to indicate it is not supposed to change after initialization
  2. Annotate a function parameter (say an Object or an Array) to guarantee that it won't be modified by the function
  3. Annotate a returned Object to indicate it is not supposed to be altered by the calling code. (This is important for closures or classes that might use the returned Object internally in the future.)

Additionally, a function could have a "pure" annotation to indicate that Flow should check that a function has no side effects. Of course, all functions called by a pure function would need to be checked for purity as well.

Preferably, immutability should apply to nested objects, such as { a : { b : 'c' }}. (In JavaScript, unfortunately, the Object.freeze() function does not prevent nested objects from being modified.)

Flow looks extremely nice, BTW. Thank you for making it open source.

Array literal can't use a union type

The following code fails to type-check:

/* @flow */

type T =
    {type: "a"; a: number} |
    {type: "b"; b: string};

var l: Array<T> = [
    {type: "a", a: 1},
    {type: "a", a: 2},
    {type: "a", a: 3},
    {type: "a", a: 4},
    {type: "b", b: "monkey"},
    {type: "b", b: "gorilla"},
    {type: "b", b: "giraffe"},
    {type: "b", b: "penguin"},
];

because the object literals' properties don't match up. It works correctly if I initialize the array as empty and then push each element on.

Should this code work as-is? Is there a better way to do tagged enums?

Support for multiple exports statements

Flow incorrectly warns me about "property not found" on an exported object, if I have multiple export statements like this:

exports.prop1 = 1;
exports.prop2 = 2;
exports.prop3 = 3;
../module2.js:3:13,34: property prop1
Property not found in
  ../module1.js: exports

If I just export it as a single object it's happy again:

exports = {
  prop1: 1,
  prop2: 2,
  prop3: 3
}

Node module not recognized

Hi,

I have react-router installed as an npm module, and it's in the node_modules folder, but everything i run flow, i get the same error

/components/content/item/ContentItemList.js:8:14,36: react-router
Required module not found

I tried adding the node_modules folder to .flowconfig but no luck, any ideas? The node_modules folder is at the same level as .flowconfig

Type annotations in comments?

Didn't see support for this in the documentation, but it would be great if Flow supported type annotations in comments (or similar) – with the aim of allowing everything to be written in pure JavaScript.

This would allow people to keep the same tools they currently use, and skip the transpilation step.

Has this idea been floated at all? Is it doable?

Edit:
Looks like this is doable – perhaps the documentation just needs to be updated to expound on this?
Edit again:
OK, so atm it's just conversion from docblock to flow – would be great if it could be done in-place... or something

Support for TypeScript definition files

After the first look on Flow I can say it is inlined Typescript. Are you planning to support .d.ts definitions to make type headers unified? And what about es6 state? Does flow support it?

Issue with: Property cannot be accessed on possibly null value

I have modified your example 03_Null/nulls.js:

/* @flow */
var x = null;
function length() {
    if (x === null) {
        return 0;
    }
    return x.length;
}

var total = length("Hello") + length();

When I run flow on this file I get following error:

nulls.js:7:16,23: property length
Property cannot be accessed on possibly null value
nulls.js:2:13,16: null

But, if I move line var x = null; inside function length, everything will work as expected. It looks like flow doesn't work well with variables outside it's scope.

Tagged enum inference with string literal types isn't sophisticated enough

Ideally this would type-check

/* @flow */

type T =
    {type: "a"; a: number} |
    {type: "b"; b: string};

function foo(x: T): string {
    if (x.type === "a") {
        return "" + x.a;
    } else {  // or else if (x.type === "b")
        return x.b;
    }
}

but it gives

test.js:9:21,23: property a
Property not found in
  test.js:5:5,26: object type

test.js:11:16,18: property b
Property not found in
  test.js:4:5,26: object type

(Let me know if I'm just misunderstanding how string types work.)

Support Generic Constraint

example from typescript handbook

interface Lengthwise {
    length: number;
}

function loggingIdentity<T extends Lengthwise>(arg: T): T {
    console.log(arg.length);  
    return arg;
}

Ignore Files and relative paths

So far I have only been able to get abosolute paths working

Example

[ignore]
/Users/john_doe/dev/project/app/assets/javascripts/_bundle.js

Over

[ignore]
./app/assets/javascripts/_bundle.js

Flow thinks conditional throwing leaves variables uninitialized

If I have code like the following

/* @flow */

function f(x: number): number {
    var y;
    if (x < 0) {
        throw new Error();
    } else {
        y = Math.sqrt(x);
    }
    return y;
}

then Flow complains that y (undefined) is incompatible with number because it doesn't get properly initialized. If you add y = 0; on the line after the throw then no errors are thrown – ideally Flow would recognize the semantics of the throw statement here and know that the return statement isn't reached in the case that an error is thrown.

Implement a Webpack loader

We use webpack for transforming JSX to JS, dependency management, and concatenation. It would be lovely if Flow was callable as a Webpack loader:

    {
      "test":   /\.jsx?$/,
      "loader": "react-hot-loader!flow-loader!jsx-loader?harmony"
    },

Create a Sublime Text plugin

IMO, A simple JSLint-like with live margin icons and warnings/errors would be huge. Do you have that in plan? Are you interested?

function purity analysis

Function purity analysis sounds amazing.

Can you give more details on how you would approach this and what the timeline might be.

custom NODE_PATH and requires

Given following files:

env.js:

var path  = require('path');
process.env.NODE_PATH = process.env.NODE_PATH + ':' + path.join(__dirname, 'lib');
require('module').Module._initPaths();

app.js

/**
 * @flow
 */
require('./env');
var Model = require('models/Foo');

lib/models/Foo.js:

module.exports = {};

running flow prints

/Users/nnarhinen/projects/flowtest/app.js:.... models/Foo
Required module not found

Also I tried to give NODE_PATH env-var when running flow. Not helping.

Support non-standard DOM properties

The following code

function getInnerText(el: Element): string {
  return el.textContent || el.innerText || '';
}

outputs

getInnerText.js:5:28,39: property innerText
Property not found in .../lib/dom.js:272:1,299:1: Element

getInnerText.js:5:28,39: property innerText
Property not found in .../lib/dom.js:301:1,316:1: HTMLElement

Indeed, innerText is non-standard, but how do I get around this?

Add ability to declare module interfaces by path

Based on conversations in IRC, it seems like the declare module Foo {} syntax for interfaces doesn't support paths. This is bad news for CommonJS, where imports like this are common:

var MyMixin = require('some-module/mixins/MyMixin');

The easiest way to fix this would be to allow a string in the declare module syntax, like:

declare module "some-module/mixins/MyMixin" {}

The same could work for relative imports (e.g. require('../foo/bar'), assuming that Flow can resolve a "full path" from the directory of the file. For example:

// foo/bar/baz.js
var MyMixin = require('../mixins/MyMixin');

should be use the declaration from:

declare module "foo/bar/mixins/MyMixin" {}

assuming that foo is the root of the project.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.