Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?

Trying Flow on my node.js code…Let’s see how this goes

Finding the getting started guide:

  1. google flow
  2. click “getflow.com”
  3. was something else
  4. google flow javascript
  5. found flowtype.org
  6. Click “get started” and landed here https://flowtype.org/docs/getting-started.html#_

Following the guide:

First thoughts, okay this is for a new project, but I’m not making a new project, so adapting to my life. In this case we’ll try with my node.js project.

  1. touch .flowconfig
  2. npm install --save-dev flow-bin
  3. Add // @flow to my index.js file // seems gross to me, but doing it anyway
  4. Typing npm run-script flow thought maybe it would work, but it doesn’t. get “missing script: flow”
  5. Typing ./node_modules/.bin/flow instead (not from docs)
  6. lots of weird startup stuff…. “flow is still initializing”
  7. “Found 43 errors”
node_modules/findup/test/fixture/f/e/d/c/b/a/top.json:1
  1: 
     ^ Unexpected end of input

node_modules/findup/test/fixture/f/e/d/c/config.json:1
  1: 
     ^ Unexpected end of input
.... // goes on an on

Errors some pretty unrelated to anything I'm doing. Giving up.

Will Try Some More Things....

  1. google the error messages
  2. Found https://github.com/facebook/flow/issues/1420#issuecomment-187619007 trying it
  3. "Found 49 errors" > 6 more errors than last time!!?!?
  4. Okay there's a not about the main field with that regex, trying another regex .*/node_modules/.*/\(lib\|test\).*\.json$
  5. "Found 36 errors" > hey progress
  6. Let's look at the last two
node_modules/react/node_modules/fbjs/lib/Deferred.js.flow:60
 60:     Promise.prototype.done.apply(this._promise, arguments);
                           ^^^^ property `done`. Property not found in
497: declare class Promise<+R> {
     ^ Promise. See lib: /private/tmp/flow/flowlib_22c9017e/core.js:497

node_modules/react/node_modules/fbjs/lib/shallowEqual.js.flow:29
 29:     return x !== 0 || 1 / (x: $FlowIssue) === 1 / (y: $FlowIssue);
  1. Seems like facebook is breaking flow. Pretty weird.
  2. Googling it.
  3. Found https://github.com/facebook/draft-js/issues/305
  4. @zpao says we need to update fbjs. I don't even use that dep directly, so I don't agree.
  5. Getting annoyed again, but running npm ls fbjs
p2pnodeweb@1.29.0 /Users/jamuferguson/dev/paypal/web
├─┬ flux@2.1.1
│ └─┬ fbemitter@2.0.2
│   └── fbjs@0.7.2 
└─┬ react@15.3.1
  └── fbjs@0.8.4 
  1. grep 'version":' ./node_modules/fbjs/package.json
  2. "0.1.0-alpha.7"
  3. Hmm, seems old npm i fbjs
  4. grep 'version":' ./node_modules/fbjs/package.json
  5. "version": "0.8.4"
  6. seems better, let's
  7. ./node_modules/.bin/flow
  8. "Found 38 Errors" > Okay ,that's 2 more than before" and more JSON errors in there

giving up again, for now

@xjamundx

This comment has been minimized.

Copy link
Owner Author

@xjamundx xjamundx commented Aug 29, 2016

With some suggestions updated my flowconfig:

[options]
suppress_type=$FlowIssue
suppress_type=$FlowFixMe

[ignore]
.*/node_modules/.*[^e]\.json$
.*/node_modules/.*\(lib\|test\).*\.json$

Now get only 33 errors

node_modules/consumerweb-mocks/dummyData/rpsProfile.json:1
  1: 
     ^ Unexpected end of input

node_modules/fbemitter/node_modules/fbjs/lib/Deferred.js.flow:25
 25:   _promise: Promise;
                 ^^^^^^^ Promise. Application of polymorphic type needs <list of 1 argument>. (Can use `*` for inferrable ones)

node_modules/fbemitter/node_modules/fbjs/lib/Deferred.js.flow:37
 37:   getPromise(): Promise {
                     ^^^^^^^ Promise. Application of polymorphic type needs <list of 1 argument>. (Can use `*` for inferrable ones)

node_modules/fbemitter/node_modules/fbjs/lib/Deferred.js.flow:51
 51:   then(): Promise {
               ^^^^^^^ Promise. Application of polymorphic type needs <list of 1 argument>. (Can use `*` for inferrable ones)

node_modules/fbemitter/node_modules/fbjs/lib/Deferred.js.flow:56
 56:     Promise.prototype.done.apply(this._promise, arguments);
                           ^^^^ property `done`. Property not found in
497: declare class Promise<+R> {
     ^ Promise. See lib: /private/tmp/flow/flowlib_dffaaca/core.js:497

node_modules/fbemitter/node_modules/fbjs/lib/PromiseMap.js.flow:15
 15: var Deferred = require('Deferred');
                    ^^^^^^^^^^^^^^^^^^^ Deferred. Required module not found

node_modules/fbemitter/node_modules/fbjs/lib/PromiseMap.js.flow:31
 31:   get(key: string): Promise {
                         ^^^^^^^ Promise. Application of polymorphic type needs <list of 1 argument>. (Can use `*` for inferrable ones)

node_modules/fbemitter/node_modules/fbjs/lib/fetchWithRetries.js.flow:16
 16: var ExecutionEnvironment = require('ExecutionEnvironment');
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ExecutionEnvironment. Required module not found

node_modules/fbemitter/node_modules/fbjs/lib/fetchWithRetries.js.flow:18
 18: var sprintf = require('sprintf');
                   ^^^^^^^^^^^^^^^^^^ sprintf. Required module not found

node_modules/fbemitter/node_modules/fbjs/lib/fetchWithRetries.js.flow:19
 19: var fetch = require('fetch');
                 ^^^^^^^^^^^^^^^^ fetch. Required module not found

node_modules/fbemitter/node_modules/fbjs/lib/fetchWithRetries.js.flow:43
 43: ): Promise {
        ^^^^^^^ Promise. Application of polymorphic type needs <list of 1 argument>. (Can use `*` for inferrable ones)

node_modules/fbjs/lib/Deferred.js.flow:60
 60:     Promise.prototype.done.apply(this._promise, arguments);
                           ^^^^ property `done`. Property not found in
497: declare class Promise<+R> {
     ^ Promise. See lib: /private/tmp/flow/flowlib_dffaaca/core.js:497

node_modules/flux/flow/include/FluxContainer.js:14
 14: var FluxStoreGroup = require('FluxStoreGroup');
                          ^^^^^^^^^^^^^^^^^^^^^^^^^ FluxStoreGroup. Required module not found

node_modules/flux/flow/include/FluxContainer.js:17
 17: var shallowEqual = require('shallowEqual');
                        ^^^^^^^^^^^^^^^^^^^^^^^ shallowEqual. Required module not found

node_modules/flux/flow/include/FluxContainer.js:40
 40: ): ReactClass<DefaultProps, Props, State> {
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type application of identifier `ReactClass`. Too many type arguments. Expected at most 1
104: type ReactClass<Config> = _ReactClass<*, *, Config, *>;
                     ^^^^^^ See type parameters of definition here. See lib: /private/tmp/flow/flowlib_dffaaca/react.js:104

node_modules/flux/flow/include/FluxMapStore.js:15
 15: import type Dispatcher from 'Dispatcher';
                                 ^^^^^^^^^^^^ Dispatcher. Required module not found

node_modules/flux/flow/include/FluxMapStore.js:17
 17: var FluxReduceStore = require('FluxReduceStore');
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^ FluxReduceStore. Required module not found

node_modules/flux/flow/include/FluxMixinLegacy.js:15
 15: import type * as FluxStore from 'FluxStore';
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ import type * as FluxStore. This is invalid syntax. Maybe you meant: `import type FluxStore from "FluxStore"`?

node_modules/flux/flow/include/FluxMixinLegacy.js:15
 15: import type * as FluxStore from 'FluxStore';
                                     ^^^^^^^^^^^ FluxStore. Required module not found

node_modules/flux/flow/include/FluxMixinLegacy.js:17
 17: var FluxStoreGroup = require('FluxStoreGroup');
                          ^^^^^^^^^^^^^^^^^^^^^^^^^ FluxStoreGroup. Required module not found

node_modules/flux/flow/include/FluxReduceStore.js:15
 15: import type Dispatcher from 'Dispatcher';
                                 ^^^^^^^^^^^^ Dispatcher. Required module not found

node_modules/flux/flow/include/FluxReduceStore.js:17
 17: var FluxStore = require('FluxStore');
                     ^^^^^^^^^^^^^^^^^^^^ FluxStore. Required module not found

node_modules/flux/flow/include/FluxReduceStore.js:19
 19: var abstractMethod = require('abstractMethod');
                          ^^^^^^^^^^^^^^^^^^^^^^^^^ abstractMethod. Required module not found

node_modules/flux/flow/include/FluxStore.js:15
 15: import type Dispatcher from 'Dispatcher';
                                 ^^^^^^^^^^^^ Dispatcher. Required module not found

node_modules/flux/flow/include/FluxStoreGroup.js:15
 15: import type Dispatcher from 'Dispatcher';
                                 ^^^^^^^^^^^^ Dispatcher. Required module not found

node_modules/flux/flow/include/FluxStoreGroup.js:16
 16: import type FluxStore from 'FluxStore';
                                ^^^^^^^^^^^ FluxStore. Required module not found

node_modules/flux/flow/include/FluxStoreGroup.js:55
 55:   if (__DEV__) {
           ^^^^^^^ identifier `__DEV__`. Could not resolve name

node_modules/flux/node_modules/fbjs/flow/include/PromiseMap.js:15
 15: var Deferred = require('Deferred');
                    ^^^^^^^^^^^^^^^^^^^ Deferred. Required module not found

node_modules/flux/node_modules/fbjs/flow/include/PromiseMap.js:19
 19: import type * as Promise from 'Promise';
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ import type * as Promise. This is invalid syntax. Maybe you meant: `import type Promise from "Promise"`?

node_modules/flux/node_modules/fbjs/flow/include/fetchWithRetries.js:16
 16: var ExecutionEnvironment = require('ExecutionEnvironment');
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ExecutionEnvironment. Required module not found

node_modules/flux/node_modules/fbjs/flow/include/fetchWithRetries.js:19
 19: var sprintf = require('sprintf');
                   ^^^^^^^^^^^^^^^^^^ sprintf. Required module not found

node_modules/flux/node_modules/fbjs/flow/include/fetchWithRetries.js:20
 20: var fetch = require('fetch');
                 ^^^^^^^^^^^^^^^^ fetch. Required module not found

node_modules/react/node_modules/fbjs/lib/Deferred.js.flow:60
 60:     Promise.prototype.done.apply(this._promise, arguments);
                           ^^^^ property `done`. Property not found in
497: declare class Promise<+R> {
     ^ Promise. See lib: /private/tmp/flow/flowlib_dffaaca/core.js:497

The first one seems valid, the rest just seem random

@xjamundx

This comment has been minimized.

Copy link
Owner Author

@xjamundx xjamundx commented Aug 29, 2016

Added .*/node_modules/flux/* to the [ignore] thing and we only have 13 errors now. Again at this point I'm gritting my teeth pretty hard, but it seems to be getting better.

@xjamundx

This comment has been minimized.

Copy link
Owner Author

@xjamundx xjamundx commented Aug 29, 2016

Slightly worried that I'm breaking things. Like if I React to that list, it just won't type-check react right?

@xjamundx

This comment has been minimized.

Copy link
Owner Author

@xjamundx xjamundx commented Aug 29, 2016

[options]
suppress_type=$FlowIssue
suppress_type=$FlowFixMe

[ignore]
.*/node_modules/.*[^e]\.json$
.*/node_modules/.*\(lib\|test\).*\.json$
.*/node_modules/flux/*
.*/node_modules/fbemitter/*

Now only shows these 3 errors

node_modules/consumerweb-mocks/dummyData/rpsProfile.json:1
  1: 
     ^ Unexpected end of input

node_modules/fbjs/lib/Deferred.js.flow:60
 60:     Promise.prototype.done.apply(this._promise, arguments);
                           ^^^^ property `done`. Property not found in
497: declare class Promise<+R> {
     ^ Promise. See lib: /private/tmp/flow/flowlib_3c13824c/core.js:497

node_modules/react/node_modules/fbjs/lib/Deferred.js.flow:60
 60:     Promise.prototype.done.apply(this._promise, arguments);
                           ^^^^ property `done`. Property not found in
497: declare class Promise<+R> {
     ^ Promise. See lib: /private/tmp/flow/flowlib_3c13824c/core.js:497


Found 3 errors

The first one is legit (it's an empty file)

@xjamundx

This comment has been minimized.

Copy link
Owner Author

@xjamundx xjamundx commented Aug 29, 2016

Okay, seems like things are getting less crazy. Let's try adding // @flow to one of my controllers.

Now seeing this:

controllers/transfer/abc.js:111
111: export async function someMethod(req, res, next) {
                                                 ^^^ parameter `req`. Missing annotation

controllers/transfer/abc.js:111
111: export async function someMethod(req, res, next) {
                                                      ^^^ parameter `res`. Missing annotation

controllers/transfer/abc.js:111
111: export async function someMethod(req, res, next) {
                                                           ^^^^ parameter `next`. Missing annotation

controllers/transfer/abc.js:119
119:            return next()
                ^^^^^^^^^^^^^ async return. Missing annotation

controllers/transfer/abc.js:125
125:            return next()
                ^^^^^^^^^^^^^ async return. Missing annotation

...
@xjamundx

This comment has been minimized.

Copy link
Owner Author

@xjamundx xjamundx commented Aug 29, 2016

So you can do this

function controllerMethod(req: http$ClientRequest, res: http$ServerResponse) {
@xjamundx

This comment has been minimized.

Copy link
Owner Author

@xjamundx xjamundx commented Aug 30, 2016

screen shot 2016-08-29 at 7 45 12 pm

@xjamundx

This comment has been minimized.

Copy link
Owner Author

@xjamundx xjamundx commented Aug 30, 2016

That worked pretty well, now running into this one:

363: export async function middleware(req: http$ClientRequest, res: http$ServerResponse, next) {
                                                                                             ^^^^ parameter `next`. Missing annotation
@xjamundx

This comment has been minimized.

Copy link
Owner Author

@xjamundx xjamundx commented Aug 30, 2016

We can call next a function. Pretty easy. next: function

@xjamundx

This comment has been minimized.

Copy link
Owner Author

@xjamundx xjamundx commented Aug 30, 2016

so (req, res, next) becomes (req: http$ClientRequest, res: http$ServerResponse, next: function)

@xjamundx

This comment has been minimized.

Copy link
Owner Author

@xjamundx xjamundx commented Aug 30, 2016

Now we're getting this error:

controllers/app/file.js:79                                                                                                
 79:            toAmount: req.query.amount                                                                                             
                              ^^^^^ property `query`. Property not found in                                                            
 79:            toAmount: req.query.amount                                                                                             
                          ^^^ http$ClientRequest            

Which I assume means that while it knows about the vanilla node.js req it doens't know about express specific properties like req.query.

@xjamundx

This comment has been minimized.

Copy link
Owner Author

@xjamundx xjamundx commented Aug 30, 2016

Found a solution here:
http://stackoverflow.com/questions/39218191/import-type-definition-for-express/39218378#39218378

Also any would probably fine for those types, because it's a mess anyway.

@xjamundx

This comment has been minimized.

Copy link
Owner Author

@xjamundx xjamundx commented Aug 30, 2016

Now seeing a ton of:

118:            return next()
                ^^^^^^^^^^^^^ async return. Missing annotation

I assume the problem here is that it's doesn't like that we use this shortcut to return and call next() on the same line, because technically it will return the results of the next() function (which is usualy nothing).

Maybe adding : void to the function declaration will help?

Or maybe I'll have to do:

next()
return
@xjamundx

This comment has been minimized.

Copy link
Owner Author

@xjamundx xjamundx commented Aug 30, 2016

Nothing seems to work.

Here's the results of trying return void next()

118:            return void next()
                ^^^^^^^^^^^^^^^^^^ async return. Missing annotation

Here's the results of putting them on separate lines:

119:            return
                ^^^^^^ async return. Missing annotation
@xjamundx

This comment has been minimized.

Copy link
Owner Author

@xjamundx xjamundx commented Aug 30, 2016

And async function always returns a Promise, so maybe it's getting confused? Or maybe there's just some special way that it needs to be annotated.

@xjamundx

This comment has been minimized.

Copy link
Owner Author

@xjamundx xjamundx commented Aug 30, 2016

Okay got it. While I think it should be built-in, adding this to the end of the functional declaration seems to work

: Promise<void>

So our async middleware looks like this:

async function middleware(req: ExpressReq, res: any, next: function): Promise<void> {
@xjamundx

This comment has been minimized.

Copy link
Owner Author

@xjamundx xjamundx commented Aug 30, 2016

Now running into this issue:

 const [contacts, fancyList: CustomType[] = [], randomThing = ''] = results
                                         ^^^^^^^^^^^^^^^^^^^ assignment of identifier `randomThing`. Could not resolve name

But I think it will be sorted out by:
facebook/flow#2239

@xjamundx

This comment has been minimized.

Copy link
Owner Author

@xjamundx xjamundx commented Aug 30, 2016

Was still getting these errors

node_modules/fbjs/lib/Deferred.js.flow:60
 60:     Promise.prototype.done.apply(this._promise, arguments);
                           ^^^^ property `done`. Property not found in
[libs]
497: declare class Promise<+R> {
     ^ Promise. See lib: /private/tmp/flow/flowlib_25b721b0/core.js:497

node_modules/react/node_modules/fbjs/lib/Deferred.js.flow:60
 60:     Promise.prototype.done.apply(this._promise, arguments);
                           ^^^^ property `done`. Property not found in
497: declare class Promise<+R> {
     ^ Promise. See lib: /private/tmp/flow/flowlib_25b721b0/core.js:497

So I added the following to the [ignore]:

.*/node_modules/.*fbjs/*
@xjamundx

This comment has been minimized.

Copy link
Owner Author

@xjamundx xjamundx commented Aug 30, 2016

Now trying to get babel to work. Seems kind of busted. Lots of these errors.

express-session deprecated undefined saveUninitialized option; provide saveUninitialized option node_modules/kraken-js/node_modules/meddleware/index.js:105:20
express-session deprecated req.secret; provide secret option node_modules/kraken-js/node_modules/meddleware/index.js:105:20
Tue, 30 Aug 2016 04:34:14 GMT unhandledRejection
SyntaxError: /Users/jamuferguson/dev/paypal/code/controllers/app/controller.js: Unexpected token (110:76)
  109 |  */
> 110 | export async function middleware(req: ExpressReq, res: any, next: function): Promise<void> {
      |                                                                             ^
  111 | 
    at Parser.pp.raise (/Users/jamuferguson/dev/paypal/code/node_modules/babylon/lib/parser/location.js:22:13)
    at Parser.pp.unexpected (/Users/jamuferguson/dev/paypal/code/node_modules/babylon/lib/parser/util.js:91:8)
    at Parser.pp.flowParsePrimaryType (/Users/jamuferguson/dev/paypal/code/node_modules/babylon/lib/plugins/flow.js:1101:8)
@xjamundx

This comment has been minimized.

Copy link
Owner Author

@xjamundx xjamundx commented Aug 30, 2016

I guess we need to do this instead?

Replace next: function with next: Function

Weird that flow didn't mind the issue. Not actually seeing how to annotate functions very clearly. Looking here:
https://flowtype.org/docs/functions.html

@eliranmal

This comment has been minimized.

Copy link

@eliranmal eliranmal commented Mar 22, 2017

this is totally fascinating.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.