facebook / flow Goto Github PK
View Code? Open in Web Editor NEWAdds static typing to JavaScript to improve developer productivity and code quality.
Home Page: https://flow.org/
License: MIT License
Adds static typing to JavaScript to improve developer productivity and code quality.
Home Page: https://flow.org/
License: MIT License
IMO, A simple JSLint-like with live margin icons and warnings/errors would be huge. Do you have that in plan? Are you interested?
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"
},
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
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.
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
.
example from typescript handbook
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length);
return arg;
}
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'"
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?
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.
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
}
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
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
Will you publish it to npm?
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.
I already started building this, just opened this for tracking.
Currently blocked on benjamn/ast-types/pull/77
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.)
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 :
Function purity analysis sounds amazing.
Can you give more details on how you would approach this and what the timeline might be.
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?
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?
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.
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?
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
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:
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.
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.
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 ?
That way this configuration can live with the project in source control.
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).
It would be great if the readme or wiki states the differences/similarities between JSDoc (or any other tools) and flow. Thanks
I have fallen in love with 6to5 and traceur's support for async/await. I would love to be able to use this with flow.
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?
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.
There's a whole lot of Windows developers out there who would love to use this too, and who will contribute based on it.
It would be nice to mark an object return value as being "immutable"
This would mean having flow error if the return value of an argument was mutated.
This would fall under the future plans section along with function purity analysis.
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
{ foo }
turns into { foo: foo }
)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.
example :
interface Mappable<M<A>> {
map<B>(func: (a:A) => B): M<B>;
}
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).
Flow says Required module not found
for var ws = require('ws.js');
Where ws.js
is installed by npm install --save ws.js
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.
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 😄
Would be super nice if i could:
brew install flow
The React example walkthrough contains several instances of object types like:
type RawMessage = {
id: string;
threadID: string;
authorName: string;
timestamp: number;
text: string;
};
but this form of definition isn't covered by the objects section of the language reference.
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.
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.
It would be nice if Flow could run on other file extensions – in particular, *.jsx
which many people use for React.
Provide a site where users can experiment with flow like the typescript playground.
http://www.typescriptlang.org/Playground
It's a great way to aid adoption.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.