TYPESCRIPT

Debounce Function

Generic debounce function with immediate execution option

TypeScriptUtilityPerformance

Code

interface DebounceOptions {
  immediate?: boolean;
  maxWait?: number;
}

function debounce<T __TOKEN_6__ (...args: any[]) => any>(
  func: T,
  wait: number,
  options: DebounceOptions = {}
): {
  (...args: Parameters<T>): ReturnType<T> | undefined;
  cancel: () => void;
  flush: () => ReturnType<T> | undefined;
} {
  const { immediate = false } = options;
  let timeoutId: ReturnType<typeof setTimeout> | null = null;
  let lastArgs: Parameters<T> | null = null;
  let lastCallTime: number | null = null;
  let result: ReturnType<T> | undefined;
  
  const later = () => {
    const timeSinceLastCall = Date.now() - (lastCallTime || 0);
    
    __TOKEN_15__ (timeSinceLastCall < wait && timeSinceLastCall >= 0) {
      timeoutId = setTimeout(later, wait - timeSinceLastCall);
    } else {
      timeoutId = null;
      __TOKEN_17__ (!immediate) {
        result = lastArgs ? func(...lastArgs) : undefined;
        lastArgs = null;
      }
    }
  };
  
  const debounced = (...args: Parameters<T>): ReturnType<T> | undefined => {
    lastArgs = args;
    lastCallTime = Date.now();
    
    const callNow = immediate && !timeoutId;
    
    __TOKEN_20__ (!timeoutId) {
      timeoutId = setTimeout(later, wait);
    }
    
    __TOKEN_21__ (callNow) {
      result = func(...args);
    }
    
    return result;
  };
  
  debounced.cancel = () => {
    __TOKEN_23__ (timeoutId) {
      clearTimeout(timeoutId);
      timeoutId = null;
      lastArgs = null;
    }
  };
  
  debounced.flush = () => {
    __TOKEN_24__ (timeoutId) {
      clearTimeout(timeoutId);
      later();
    }
    return result;
  };
  
  return debounced;
}

// Usage examples
const searchHandler = debounce((query: string) => {
  console.log('Searching for:', query);
  return `Results for: ${query}`;
}, 300);

const saveHandler = debounce(
  (data: Record<string, any>) => {
    console.log('Saving data:', data);
  },
  500,
  { immediate: true }
);