Skip to content

Commit

Permalink
Merge pull request #12 from alexreardon/improved-flow-typing
Browse files Browse the repository at this point in the history
Improved flow type
  • Loading branch information
alexreardon authored May 15, 2017
2 parents 5cb7ffc + 14e875c commit bdd0e37
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 17 deletions.
1 change: 1 addition & 0 deletions .babelrc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"presets": [
"es2015"
],
"comments": false,
"plugins": [
"transform-object-rest-spread",
"transform-flow-strip-types"
Expand Down
4 changes: 4 additions & 0 deletions .flowconfig
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

[options]

# Opting in to 'Strict Checking of Function Call Arity'
# https://flow.org/blog/2017/05/07/Strict-Function-Call-Arity/
experimental.strict_call_arity=true

# Provides a way to suppress flow errors in the following line.
# Example: // $FlowFixMe: This following line is borked because of reasons.
suppress_comment= \\(.\\|\n\\)*\\$FlowFixMe
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"codecov": "2.1.0",
"eslint": "3.19.0",
"eslint-plugin-flowtype": "2.32.1",
"flow-bin": "0.45.0",
"flow-bin": "0.46.0",
"flow-copy-source": "1.1.0",
"mocha": "3.3.0",
"nyc": "10.3.0",
Expand Down
35 changes: 22 additions & 13 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,28 @@
// @flow
type EqualityFn = (a: any, b: any) => boolean;
type EqualityFn = (a: mixed, b: mixed) => boolean;

const simpleIsEqual = (a: any, b: any): boolean => a === b;
const simpleIsEqual: EqualityFn = (a: mixed, b: mixed): boolean => a === b;

export default function (resultFn: Function, isEqual?: EqualityFn = simpleIsEqual) {
let lastThis: any;
let lastArgs: Array<any> = [];
let lastResult: any;
// <ResultFn: (...Array<any>) => mixed>
// The purpose of this typing is to ensure that the returned memoized
// function has the same type as the provided function (`resultFn`).
// ResultFn: Generic type (which is the same as the resultFn).
// (...Array<any>): Accepts any length of arguments - and they are not checked
// mixed: The result can be anything but needs to be checked before usage
export default function <ResultFn: (...Array<any>) => mixed>(resultFn: ResultFn, isEqual?: EqualityFn = simpleIsEqual): ResultFn {
let lastThis: mixed;
let lastArgs: Array<mixed> = [];
let lastResult: mixed;
let calledOnce: boolean = false;

const isNewArgEqualToLast = (newArg, index) => isEqual(newArg, lastArgs[index]);
const isNewArgEqualToLast = (newArg: mixed, index: number): boolean => isEqual(newArg, lastArgs[index]);

// breaking cache when context (this) or arguments change
return function (...newArgs: Array<any>) {
// breaking cache when context (this) or arguments change
const result = function (...newArgs: Array<mixed>) {
if (calledOnce &&
lastThis === this &&
newArgs.length === lastArgs.length &&
newArgs.every(isNewArgEqualToLast)) {
lastThis === this &&
newArgs.length === lastArgs.length &&
newArgs.every(isNewArgEqualToLast)) {
return lastResult;
}

Expand All @@ -26,4 +32,7 @@ export default function (resultFn: Function, isEqual?: EqualityFn = simpleIsEqua
lastResult = resultFn.apply(this, newArgs);
return lastResult;
};
}

// telling flow to ignore the type of `result` as we know it is `ResultFn`
return (result: any);
}
18 changes: 18 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -482,5 +482,23 @@ describe('memoizeOne', () => {
expect(add.callCount).to.equal(2);
});
});

describe('flow typing', () => {
it('should maintain the type of the original function', () => {
// this test will create a flow error if the typing is incorrect
type SubtractFn = (a: number, b: number) => number;
const subtract: SubtractFn = (a: number, b: number): number => a - b;
const requiresASubtractFn = (fn: SubtractFn): number => fn(2, 1);

const memoizedSubtract: SubtractFn = memoizeOne(subtract);

// will cause a flow error if `fn` is not of type `SubtractFn`
const result1 = requiresASubtractFn(memoizedSubtract);
const result2 = requiresASubtractFn(memoizeOne(subtract));

expect(result1).to.equal(1);
expect(result2).to.equal(1);
});
});
});

6 changes: 3 additions & 3 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1190,9 +1190,9 @@ flat-cache@^1.2.1:
graceful-fs "^4.1.2"
write "^0.2.1"

flow-bin@0.45.0:
version "0.45.0"
resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.45.0.tgz#009dd0f577a3f665c74ca8be827ae8c2dd8fd6b5"
flow-bin@0.46.0:
version "0.46.0"
resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.46.0.tgz#06ad7fe19dddb1042264438064a2a32fee12b872"

flow-copy-source@1.1.0:
version "1.1.0"
Expand Down

0 comments on commit bdd0e37

Please sign in to comment.