/** * Throttles a function to limit execution frequency * * Ensures a function executes at most once per `wait` milliseconds. * Unlike debounce, throttled functions execute on the leading edge * and trailing edge if called repeatedly. * * @example * ```ts * const logScroll = throttle(() => { * console.log('Scroll position:', window.scrollY); * }, 100); * * window.addEventListener('scroll', logScroll); * // Will log at most once every 100ms * ``` * * @param fn - Function to throttle * @param wait - Minimum time between executions in milliseconds * @returns Throttled function */ export function throttle any>( fn: T, wait: number, ): (...args: Parameters) => void { let lastCall = 0; let timeoutId: ReturnType | null = null; return (...args: Parameters) => { const now = Date.now(); const timeSinceLastCall = now - lastCall; if (timeSinceLastCall >= wait) { lastCall = now; fn(...args); } else { // Schedule for end of wait period (trailing edge) if (timeoutId) { clearTimeout(timeoutId); } timeoutId = setTimeout(() => { lastCall = Date.now(); fn(...args); timeoutId = null; }, wait - timeSinceLastCall); } }; }