function memoizeOne(fn) {
  /** @type {ReturnType} */
  let lastResult;

  /** @type {Array<any>|undefined} */
  let lastArgs;

  let lastThis;

  /**
   * @this {*} Only need to know if `this` changed, don't care what type
   * @return {ReturnType} Memoized value
   */
  return function () {
    const nextArgs = Array.prototype.slice.call(arguments);
    if (!lastArgs || this !== lastThis || !arrayEquals(nextArgs, lastArgs)) {
      lastThis = this;
      lastArgs = nextArgs;
      lastResult = fn.apply(this, arguments);
    }
    return lastResult;
  };
}
Wrap a function in another function that remembers the last return.  If the
returned function is called twice in a row with the same arguments and the same
this object, it will return the value from the first call in the second call.

@param {function(...any): ReturnType} fn The function to memoize.
@return {function(...any): ReturnType} The memoized function.
@template ReturnType