Asynchronous Programming in TypeScript: A Complete Guide

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction to Asynchronous Programming in TypeScript



Modern web development is unthinkable without asynchronous programming. Whether it's API requests, working with the file system, or timers — all these operations require non-blocking code execution. TypeScript, as a superset of JavaScript, provides powerful tools for working with asynchrony, adding strict typing and improved code readability.



In this guide, we will thoroughly examine all aspects of asynchronous programming in TypeScript: from basic Promise to advanced patterns with async/await and parallel task execution.



1. Basics of Promise in TypeScript



What is a Promise?



A Promise is an object representing the result of an asynchronous operation. It can be in one of three states:



  • Pending — initial state, the operation has not completed yet.
  • Fulfilled — the operation completed successfully.
  • Rejected — the operation completed with an error.


Creating a Promise with Typing



TypeScript allows you to strictly type the return values of a Promise. Let's look at an example:



// Function returning a Promise with a data typefunction fetchUserData(userId: number): Promise<User> {    return new Promise<User>((resolve, reject) => {        setTimeout(() => {            const user: User = {                id: userId,                name: 'Ivan Ivanov',                email: 'ivan@example.com'            };                        if (userId > 0) {                resolve(user);            } else {                reject(new Error('Invalid user ID'));            }        }, 1000);    });}

// Interface for data typinginterface User { id: number; name: string; email: string;}

// Using the PromisefetchUserData(1) .then((user: User) => { console.log(`User: ${user.name}`); }) .catch((error: Error) => { console.error(`Error: ${error.message}`); });


Promise Chaining



Promises can be chained together for sequential execution of asynchronous operations:



function getUserPosts(userId: number): Promise<string[]> {    return new Promise((resolve) => {        setTimeout(() => resolve(['Post 1', 'Post 2', 'Post 3']), 500);    });}

function getPostComments(postTitle: string): Promise<string[]> { return new Promise((resolve) => { setTimeout(() => resolve(['Comment 1', 'Comment 2']), 300); });}

// Promise ChainfetchUserData(1) .then((user) => { console.log(`User found: ${user.name}`); return getUserPosts(user.id); }) .then((posts) => { console.log(`Posts found: ${posts.length}`); return getPostComments(posts[0]); }) .then((comments) => { console.log(`Comments on the first post: ${comments.length}`); }) .catch((error) => { console.error('An error occurred:', error); });


2. Async/Await — A Modern Approach



Async/Await Syntax



The async and await keywords make asynchronous code look synchronous, which significantly improves its readability. A function marked with async always returns a Promise.



// Async function with typed return valueasync function loadUserProfile(userId: number): Promise<UserProfile> {    try {        const user = await fetchUserData(userId);        const posts = await getUserPosts(userId);                return {            user,            posts,            lastLogin: new Date()        };                

Blogs

Book Recommendations