/** * Simple debounce with cancel support. Replaces lodash.debounce. */ // eslint-disable-next-line @typescript-eslint/no-explicit-any export function debounce void>( fn: T, ms: number ): T & { cancel: () => void } { let timeoutId: ReturnType | null = null const debounced = (...args: Parameters) => { if (timeoutId !== null) clearTimeout(timeoutId) timeoutId = setTimeout(() => { timeoutId = null fn(...args) }, ms) } debounced.cancel = () => { if (timeoutId !== null) { clearTimeout(timeoutId) timeoutId = null } } return debounced as T & { cancel: () => void } }