[flow] annotate accumulate and accumulateInto

Summary:
Trying to start adding flow types to files in React. I needed to add a script to package.json in order to run flow, flow-bin is already a dependency.

I had to rewrite the implementation a bit. Flow doesn't recognize

```
var currentIsArray = Array.isArray(current);
if (currentIsArray) {
  // not refined
}
```

but the following does work

```
if (Array.isArray(current)) {
  // refined
}
```

Test Plan:
npm run-script flow
npm run-script test accumulate

Reviewers: @zpao @spicyj
This commit is contained in:
Christopher Chedeau
2016-06-16 17:18:30 +02:00
parent 49238b9440
commit 1c71970431
4 changed files with 33 additions and 30 deletions

View File

@@ -78,7 +78,8 @@
"linc": "git diff --name-only --diff-filter=ACMRTUB `git merge-base HEAD master` | grep '\\.js$' | xargs eslint --",
"lint": "grunt lint",
"postinstall": "node node_modules/fbjs-scripts/node/check-dev-engines.js package.json",
"test": "jest"
"test": "jest",
"flow": "flow"
},
"jest": {
"modulePathIgnorePatterns": [

View File

@@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule accumulate
* @flow
*/
'use strict';
@@ -20,28 +21,27 @@ var invariant = require('invariant');
*
* @return {*|array<*>} An accumulation of items.
*/
function accumulate(current, next) {
function accumulate<T>(current: ?(T | Array<T>), next: T | Array<T>): T | Array<T> {
invariant(
next != null,
'accumulate(...): Accumulated items must be not be null or undefined.'
);
if (current == null) {
return next;
} else {
// Both are not empty. Warning: Never call x.concat(y) when you are not
// certain that x is an Array (x could be a string with concat method).
var currentIsArray = Array.isArray(current);
var nextIsArray = Array.isArray(next);
if (currentIsArray) {
return current.concat(next);
} else {
if (nextIsArray) {
return [current].concat(next);
} else {
return [current, next];
}
}
}
// Both are not empty. Warning: Never call x.concat(y) when you are not
// certain that x is an Array (x could be a string with concat method).
if (Array.isArray(current)) {
return current.concat(next);
}
if (Array.isArray(next)) {
return [current].concat(next);
}
return [current, next];
}
module.exports = accumulate;

View File

@@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule accumulateInto
* @flow
*/
'use strict';
@@ -14,7 +15,6 @@
var invariant = require('invariant');
/**
*
* Accumulates items that must not be null or undefined into the first one. This
* is used to conserve memory by avoiding array allocations, and thus sacrifices
* API cleanness. Since `current` can be null before being passed in and not
@@ -27,31 +27,28 @@ var invariant = require('invariant');
* @return {*|array<*>} An accumulation of items.
*/
function accumulateInto(current, next) {
function accumulateInto<T>(current: ?(T | Array<T>), next: T | Array<T>): T | Array<T> {
invariant(
next != null,
'accumulateInto(...): Accumulated items must not be null or undefined.'
);
if (current == null) {
return next;
}
// Both are not empty. Warning: Never call x.concat(y) when you are not
// certain that x is an Array (x could be a string with concat method).
var currentIsArray = Array.isArray(current);
var nextIsArray = Array.isArray(next);
if (currentIsArray && nextIsArray) {
current.push.apply(current, next);
return current;
}
if (currentIsArray) {
if (Array.isArray(current)) {
if (Array.isArray(next)) {
current.push.apply(current, next);
return current;
}
current.push(next);
return current;
}
if (nextIsArray) {
if (Array.isArray(next)) {
// A bit too dangerous to mutate `next`.
return [current].concat(next);
}

View File

@@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule forEachAccumulated
* @flow
*/
'use strict';
@@ -18,12 +19,16 @@
* handling the case when there is exactly one item (and we do not need to
* allocate an array).
*/
var forEachAccumulated = function(arr, cb, scope) {
function forEachAccumulated<T>(
arr: ?(T | Array<T>),
cb: ((elem: T) => void),
scope: ?any,
) {
if (Array.isArray(arr)) {
arr.forEach(cb, scope);
} else if (arr) {
cb.call(scope, arr);
}
};
}
module.exports = forEachAccumulated;