Writing a debounce function in TypeScript

  • TypeScript

  • JavaScript

Writing a debounce function in TypeScript

In modern web development, optimizing the performance and efficiency of applications is crucial. One common technique used to achieve this is the debounce function. This powerful tool helps manage the frequency of certain actions, particularly those that are triggered by user interactions.

In this article, we'll explore what a debounce function is, its purpose, and provide a practical example using TypeScript.

If you already know what the debounce function is, and you are just interested in how to write it in TypeScript, you can find the final code here.

What is the Debounce Function?

A debounce function limits the rate at which a particular function can be executed. Its primary purpose is to prevent a function from being called too frequently. This is especially useful in scenarios where rapid, successive function calls can lead to performance issues or unnecessary network requests. By ensuring that a function is only executed after a specified amount of time has passed since its last invocation, debounce functions help improve application efficiency and user experience.

Let's consider a practical example: we have a text input field that makes an API call each time the user types in it to fetch a list of suggestions.

TypeScript

const textInput =
document.querySelector<HTMLInputElement>('input[type="text"]');
 
textInput.addEventListener('keydown', fetchSuggestions);

Without debouncing, the API would be called every time the input changes, which could result in an excessive number of calls. By applying a debounce function, we can reduce the frequency of these API calls, ensuring they only occur when the user has paused typing for a specified period.

Implementing the Debounce Function

First, we'll define the basic structure of the debounce function. This function will accept two arguments: callback, which is the function we want to debounce, and delay, which is the delay in milliseconds.

TypeScript

const debounce = <T extends unknown[]>(
callback: (...args: T) => void,
delay: number,
) => {};

Next, we'll return a function that, when called, will execute the callback after the specified delay. This is achieved using setTimeout.

TypeScript

const debounce = <T extends unknown[]>(
callback: (...args: T) => void,
delay: number,
) => {
return (...args: T) => {
setTimeout(() => {
callback(...args);
}, delay);
};
};

To ensure that the callback is only called once the user has stopped triggering the event for the specified delay, we need to use clearTimeout. This will reset the timer each time the function is invoked before the delay period has elapsed.

TypeScript

const debounce = <T extends unknown[]>(
callback: (...args: T) => void,
delay: number,
) => {
let timeoutTimer: ReturnType<typeof setTimeout>;
 
return (...args: T) => {
clearTimeout(timeoutTimer);
 
timeoutTimer = setTimeout(() => {
callback(...args);
}, delay);
};
};

Now our debounce function is ready to be used to debounce the keydown event of our input. Let's put all the code together.

TypeScript

const debounce = <T extends unknown[]>(
callback: (...args: T) => void,
delay: number,
) => {
let timeoutTimer: ReturnType<typeof setTimeout>;
 
return (...args: T) => {
clearTimeout(timeoutTimer);
 
timeoutTimer = setTimeout(() => {
callback(...args);
}, delay);
};
};
 
const textInput =
document.querySelector<HTMLInputElement>('input[type="text"]');
 
textInput.addEventListener('keydown', debounce(fetchSuggestions, 300));

Conclusion

The debounce function is an essential tool in the web developer's toolkit, particularly when dealing with high-frequency events like keystrokes. By controlling the rate at which a function executes, debouncing helps improve application performance and user experience.