When working on asynchronous JavaScript applications with TypeScript, I often need to introduce deliberate delays in code execution. Whether it’s for rate limiting API calls, creating animations, or simulating network latency during testing, a sleep function becomes indispensable.
In this article, I’ll share multiple ways to implement a sleep function in TypeScript based on my experience. These methods will help you pause code execution elegantly without blocking the main thread.
What is a Sleep Function?
A sleep function pauses the execution of code for a specified amount of time before continuing. Unlike languages like Python or C# that have built-in sleep functions, TypeScript doesn’t have one out of the box.
However, we can easily create our own sleep function using JavaScript’s asynchronous capabilities. Let’s explore several approaches.
Check out: Function Overloading in TypeScript
Method 1: Using Promises with setTimeout in TypeScript
The most common and reliable approach is to create a Promise-based sleep function:
function sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function demo() {
console.log("Starting process...");
await sleep(2000);
console.log("Waited 2 seconds");
console.log("Continuing after delay");
}
demo();Output:

This approach wraps JavaScript’s setTimeout in a Promise, allowing you to use it with async/await syntax. It’s clean, readable, and follows modern JavaScript practices.
Check out: Spread Operator in TypeScript
Method 2: Using a One-liner Arrow Function in TypeScript
If you prefer a more concise syntax, you can implement the sleep function as an arrow function:
const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
// Usage example
async function processTransactions() {
console.log("Processing transaction 1");
await sleep(1000);
console.log("Processing transaction 2");
await sleep(1000);
console.log("All transactions completed");
}
processTransactions();Output:

This one-liner achieves the same result as Method 1 but with less code. I often use this approach in my projects for its simplicity.
Check out: TypeScript Type Narrowing
Method 3: Adding Return Value Support in TypeScript
Sometimes, you might want your sleep function to return a value after the delay. Here’s how to implement that:
function sleepWithValue<T>(ms: number, value: T): Promise<T> {
return new Promise(resolve => setTimeout(() => resolve(value), ms));
}
// Usage example
async function fetchUserData() {
console.log("Fetching user data...");
// Simulate API call with a delay that returns user data
const userData = await sleepWithValue(2000, {
id: 123,
name: "John Smith",
location: "New York",
subscription: "Premium"
});
console.log("User data received:", userData);
return userData;
}
fetchUserData();Output:

This generic implementation allows you to specify the return type and value, making it useful for mocking API responses during development or testing.
Check out: TypeScript Constructor Overloading
Method 4: Creating a Sleep Utility Class in TypeScript
For larger applications, I sometimes prefer organizing utility functions into classes:
class TimerUtils {
/**
* Pauses execution for the specified number of milliseconds
* @param ms Milliseconds to wait
*/
static sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
/**
* Executes a callback after the specified delay
* @param ms Milliseconds to wait
* @param callback Function to execute after delay
*/
static delayedExecution(ms: number, callback: () => void): void {
setTimeout(callback, ms);
}
/**
* Returns a value after the specified delay
* @param ms Milliseconds to wait
* @param value Value to return
*/
static sleepWithValue<T>(ms: number, value: T): Promise<T> {
return new Promise(resolve => setTimeout(() => resolve(value), ms));
}
}
// Usage example
async function processDataImport() {
console.log("Starting data import...");
// Wait for 1 second
await TimerUtils.sleep(1000);
console.log("Processing batch 1");
// Execute a callback after 1.5 seconds
TimerUtils.delayedExecution(1500, () => {
console.log("Callback executed");
});
// Wait and return a value
const result = await TimerUtils.sleepWithValue(2000, {
status: "success",
recordsProcessed: 1250,
errors: 0
});
console.log("Import completed:", result);
}
processDataImport();Output:

This approach provides a more organized and extensible way to handle timing-related utilities in larger applications.
Check out: Set Default Values in TypeScript Interfaces
Real-World Use Cases for Sleep Function in TypeScript
Let’s look at some practical scenarios where I’ve found sleep functions particularly useful:
1. Rate Limiting API Calls
When working with APIs that have rate limits, adding delays between requests is essential:
async function fetchUserById(id: number) {
console.log(`Calling API for user ID: ${id}`);
await sleep(100); // Simulate API response time
return { id, name: `User ${id}` };
}
// Sleep utility
function sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
// Final version of fetchAllUsers with logs
async function fetchAllUsers(userIds: number[]) {
const results = [];
console.log('Starting to fetch user data...');
for (const id of userIds) {
console.log(`Fetching user with ID: ${id}`);
const userData = await fetchUserById(id);
console.log(`Fetched data for user ${id}:`, userData);
results.push(userData);
console.log(`Waiting 300ms before next request...`);
await sleep(300);
}
console.log('Finished fetching all users.');
return results;
}
// Example usage
fetchAllUsers([101, 102, 103]).then(users => {
console.log('Final user list:', users);
});Output:

2. Creating Animations or Transitions
For UI animations that require precise timing:
async function animateProgressBar(elementId: string, targetPercent: number) {
const element = document.getElementById(elementId) as HTMLElement;
let current = 0;
while (current < targetPercent) {
current += 1;
element.style.width = `${current}%`;
element.textContent = `${current}%`;
// Smooth animation with small delays
await sleep(20);
}
}3. Testing Race Conditions
When testing asynchronous code for potential race conditions:
async function testConcurrentOperations() {
// Start two operations with different delays
const operation1 = async () => {
await sleep(100);
return "Operation 1 result";
};
const operation2 = async () => {
await sleep(50);
return "Operation 2 result";
};
// Execute concurrently
const results = await Promise.all([operation1(), operation2()]);
console.log("Results:", results);
}Output:

Check out: Create an Object from an Interface in TypeScript
Potential Pitfalls and Best Practices
While implementing sleep functions in TypeScript, I’ve encountered some common issues. Here are my recommendations:
- Don’t use sleep in critical rendering paths: Sleep functions pause execution, which can block UI updates if used improperly.
- Be mindful of memory usage: Avoid creating many pending promises in loops without proper throttling.
- Consider using cancelable sleep: For scenarios where you might need to cancel a sleep operation:
function cancelableSleep(ms: number) {
let timeoutId: NodeJS.Timeout;
const promise = new Promise<void>((resolve) => {
timeoutId = setTimeout(resolve, ms);
});
const cancel = () => {
clearTimeout(timeoutId);
};
return { promise, cancel };
}
// Usage
const { promise, cancel } = cancelableSleep(5000);
// Later, if needed
cancel(); // Cancels the sleep operationOutput:

- Use TypeScript’s typing for cleaner code: Properly typed sleep functions make your code more maintainable.
I hope you found these methods for implementing sleep functions in TypeScript helpful. These approaches have served me well across numerous projects, from small utilities to large enterprise applications.
Remember that while sleep functions are useful, they should be used judiciously. For most UI work, consider using CSS animations or requestAnimationFrame for smoother performance. For backend operations, evaluate whether actual timers or event-based approaches might be more appropriate than explicit sleep calls.

I am Bijay Kumar, a Microsoft MVP in SharePoint. Apart from SharePoint, I started working on Python, Machine learning, and artificial intelligence for the last 5 years. During this time I got expertise in various Python libraries also like Tkinter, Pandas, NumPy, Turtle, Django, Matplotlib, Tensorflow, Scipy, Scikit-Learn, etc… for various clients in the United States, Canada, the United Kingdom, Australia, New Zealand, etc. Check out my profile.