Debounce with preserved argument types
A debounce function whose returned function keeps the parameter types and exposes cancel() and flush().
- TypeScript
- GreenSnippets
- MIT
- Executed with Node.js 22 (type stripping)
function debounce<F extends (...args: never[]) => void>(fn: F, waitMs: number) {
let timer: ReturnType<typeof setTimeout> | undefined;
let lastArgs: Parameters<F> | undefined;
const run = () => {
timer = undefined;
if (lastArgs) fn(...lastArgs);
lastArgs = undefined;
};
const debounced = (...args: Parameters<F>) => {
lastArgs = args;
clearTimeout(timer);
timer = setTimeout(run, waitMs);
};
debounced.cancel = () => {
clearTimeout(timer);
timer = undefined;
lastArgs = undefined;
};
debounced.flush = () => {
if (timer !== undefined) {
clearTimeout(timer);
run();
}
};
return debounced;
}Example / expected output
const save = debounce((id: number, text: string) => api.save(id, text), 300);
save(1, "draft"); // only the last call within 300 ms runsHow it works
Parameters<F> carries the original argument list through, so callers of the debounced function still get type checking. cancel clears a pending call and flush runs it immediately, which is useful when a component unmounts or a form is submitted.
Related snippets
- JavaScript Tested
Run a function only once
Wrap a function so it executes on the first call and returns the same result afterwards.
- JavaScript Tested
Memoize a function
Cache results by argument so expensive pure functions only run once per distinct input.
- JavaScript Tested
Curry a function
Turn a multi-argument function into one that can be called a few arguments at a time.
- JavaScript Tested
Compose and pipe functions
Chain single-argument functions left-to-right with pipe, or right-to-left with compose.

