function debounce(fn, time) {
  /** @type {NodeJS.Timeout|undefined} */
  let timeout;
  const cancel = () => {
    if (timeout) clearTimeout(timeout);
    timeout = undefined;
  };

  /** @param {T} args */
  const debouncedFn = (...args) => {
    if (timeout) clearTimeout(timeout);
    timeout = setTimeout(() => fn(...args), time);
  };

  debouncedFn.cancel = cancel;
  return debouncedFn;
}
@template {any[]} T
@param {(...args: T) => void} fn
@param {number} time
@return {{(...args: T): void; cancel: () => void;}}