-
Notifications
You must be signed in to change notification settings - Fork 79
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Quality of life improvements #124
Changes from 1 commit
5c461df
be62c91
90120e0
90a96b3
d0e81d7
0012074
df7a8d5
4a50848
37c2f14
a14f72b
c925f41
a24ae2f
ef02130
240c487
4544976
d9f4df0
f9feb89
9c79669
9f3d201
60d9251
2846fd6
df61a4d
4f95b68
43dd445
c4452d3
6be9f57
df68217
e82c14a
b615c77
7adb481
a9a8f1e
1792ea7
3ee2ee9
07c60e2
9b2cb7d
2a2edcf
16844f2
21be245
7d74046
82cf3af
a26cb54
35231c9
ae6d858
806a028
752bc49
664007e
dfcf27b
e2f12d3
02911d8
f239f05
2f98c12
73f6d9b
2a2c84b
84f2b21
8b12bfb
ae7a643
dd27948
19b26b4
4872312
3e75de0
ce0c6bf
4c5409b
18b689f
cd46d47
994ef04
d8246db
e5a4d8b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,40 +1,56 @@ | ||
import areInputsEqual from './are-inputs-equal'; | ||
|
||
// Using ReadonlyArray<T> rather than readonly T as it works with TS v3 | ||
export type EqualityFn = (newArgs: any[], lastArgs: any[]) => boolean; | ||
|
||
function memoizeOne< | ||
// Need to use 'any' rather than 'unknown' here as it has | ||
// The correct Generic narrowing behaviour. | ||
ResultFn extends (this: any, ...newArgs: any[]) => ReturnType<ResultFn> | ||
>(resultFn: ResultFn, isEqual: EqualityFn = areInputsEqual): ResultFn { | ||
let lastThis: unknown; | ||
let lastArgs: unknown[] = []; | ||
let lastResult: ReturnType<ResultFn>; | ||
let calledOnce: boolean = false; | ||
export type EqualityFn<TFunc extends (...args: any[]) => any> = ( | ||
newArgs: Parameters<TFunc>, | ||
lastArgs: Parameters<TFunc>, | ||
) => boolean; | ||
|
||
type Cache<TFunc extends (this: any, ...args: any[]) => any> = { | ||
lastThis: ThisParameterType<TFunc>; | ||
lastArgs: Parameters<TFunc>; | ||
lastResult: ReturnType<TFunc>; | ||
}; | ||
|
||
type MemoizedFn<TFunc extends (this: any, ...args: any[]) => any> = { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Previously we were casting the return value to be return memoized as ResultFn; That is technically not correct as we are not maintaining any properties on the function itself. We now return a function that has the same type as the functions call signature and we are explicitly adding a |
||
clear: () => void; | ||
(this: ThisParameterType<TFunc>, ...args: Parameters<TFunc>): ReturnType<TFunc>; | ||
}; | ||
|
||
function memoizeOne<TFunc extends (this: any, ...newArgs: any[]) => any>( | ||
resultFn: TFunc, | ||
isEqual: EqualityFn<TFunc> = areInputsEqual, | ||
): MemoizedFn<TFunc> { | ||
let cache: Cache<TFunc> | null = null; | ||
|
||
// breaking cache when context (this) or arguments change | ||
function memoized(this: unknown, ...newArgs: unknown[]): ReturnType<ResultFn> { | ||
if (calledOnce && lastThis === this && isEqual(newArgs, lastArgs)) { | ||
return lastResult; | ||
function memoized( | ||
this: ThisParameterType<TFunc>, | ||
...newArgs: Parameters<TFunc> | ||
): ReturnType<TFunc> { | ||
if (cache && cache.lastThis === this && isEqual(newArgs, cache.lastArgs)) { | ||
return cache.lastResult; | ||
} | ||
|
||
// Throwing during an assignment aborts the assignment: https://codepen.io/alexreardon/pen/RYKoaz | ||
// Doing the lastResult assignment first so that if it throws | ||
// nothing will be overwritten | ||
lastResult = resultFn.apply(this, newArgs); | ||
calledOnce = true; | ||
lastThis = this; | ||
lastArgs = newArgs; | ||
// the cache will be overwritten | ||
const lastResult = resultFn.apply(this, newArgs); | ||
cache = { | ||
lastResult, | ||
lastArgs: newArgs, | ||
lastThis: this, | ||
}; | ||
|
||
return lastResult; | ||
} | ||
|
||
return memoized as ResultFn; | ||
// Adding the ability to clear the cache of a memoized function | ||
memoized.clear = function clear() { | ||
cache = null; | ||
}; | ||
|
||
return memoized; | ||
} | ||
|
||
// default export | ||
export default memoizeOne; | ||
|
||
// disabled for now as mixing named and | ||
// default exports is problematic with CommonJS | ||
// export { memoizeOne }; |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The types of the EqualityFn are now based on the function that it is being used for