Claude
Skills
Sign in
Back

typescript-async-patterns

Included with Lifetime
$97 forever

Use when typeScript async patterns including Promises, async/await, and async iterators with proper typing. Use when writing asynchronous TypeScript code.

Writing & Docs

What this skill does


# TypeScript Async Patterns

Master asynchronous programming patterns in TypeScript, including Promises,
async/await, error handling, async iterators, and advanced patterns for
building robust async applications.

## Promises and async/await

### Basic Promise Creation

```typescript
// Creating a Promise
function delay(ms: number): Promise<void> {
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
}

// Promise with value
function fetchUserData(userId: string): Promise<User> {
  return new Promise((resolve, reject) => {
    // Simulated API call
    setTimeout(() => {
      if (userId) {
        resolve({ id: userId, name: 'John Doe' });
      } else {
        reject(new Error('Invalid user ID'));
      }
    }, 1000);
  });
}

// Using the Promise
fetchUserData('123')
  .then((user) => {
    console.log(user.name);
  })
  .catch((error) => {
    console.error('Error:', error.message);
  });
```

### async/await Syntax

```typescript
interface User {
  id: string;
  name: string;
  email: string;
}

interface Post {
  id: string;
  userId: string;
  title: string;
  content: string;
}

// Async function declaration
async function getUserPosts(userId: string): Promise<Post[]> {
  try {
    const user = await fetchUserData(userId);
    const posts = await fetchPostsByUser(user.id);
    return posts;
  } catch (error) {
    console.error('Failed to fetch user posts:', error);
    throw error;
  }
}

// Async arrow function
const getUserProfile = async (userId: string): Promise<User> => {
  const user = await fetchUserData(userId);
  return user;
};

// Using async/await
async function main() {
  const posts = await getUserPosts('123');
  console.log(`Found ${posts.length} posts`);
}
```

### Type-Safe Promise Wrappers

```typescript
type Result<T, E = Error> =
  | { success: true; data: T }
  | { success: false; error: E };

async function safeAsync<T>(
  promise: Promise<T>
): Promise<Result<T>> {
  try {
    const data = await promise;
    return { success: true, data };
  } catch (error) {
    return {
      success: false,
      error: error instanceof Error ? error : new Error(String(error)),
    };
  }
}

// Usage
async function example() {
  const result = await safeAsync(fetchUserData('123'));

  if (result.success) {
    console.log(result.data.name);
  } else {
    console.error(result.error.message);
  }
}
```

## Promise Chaining and Composition

### Chaining Promises

```typescript
interface ApiResponse<T> {
  data: T;
  status: number;
}

function fetchData<T>(url: string): Promise<ApiResponse<T>> {
  return fetch(url)
    .then((response) => {
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }
      return response.json();
    })
    .then((data) => ({
      data,
      status: 200,
    }));
}

// Chaining multiple async operations
function processUserData(userId: string): Promise<string> {
  return fetchUserData(userId)
    .then((user) => fetchPostsByUser(user.id))
    .then((posts) => posts.filter((post) => post.title.includes('TypeScript')))
    .then((filteredPosts) => `Found ${filteredPosts.length} TypeScript posts`)
    .catch((error) => {
      console.error('Error in chain:', error);
      return 'Failed to process user data';
    });
}
```

### Composing Async Functions

```typescript
type AsyncFunction<T, R> = (input: T) => Promise<R>;

function pipe<T, A, B>(
  fn1: AsyncFunction<T, A>,
  fn2: AsyncFunction<A, B>
): AsyncFunction<T, B> {
  return async (input: T) => {
    const result1 = await fn1(input);
    return fn2(result1);
  };
}

// Usage
const getUserId = async (username: string): Promise<string> => {
  // Look up user ID
  return '123';
};

const getUserData = async (userId: string): Promise<User> => {
  return fetchUserData(userId);
};

const getUserByUsername = pipe(getUserId, getUserData);

// Use the composed function
const user = await getUserByUsername('johndoe');
```

## Error Handling in Async Code

### Try-Catch with async/await

```typescript
class ApiError extends Error {
  constructor(
    message: string,
    public statusCode: number,
    public response?: unknown
  ) {
    super(message);
    this.name = 'ApiError';
  }
}

async function fetchWithErrorHandling<T>(url: string): Promise<T> {
  try {
    const response = await fetch(url);

    if (!response.ok) {
      throw new ApiError(
        `HTTP error! status: ${response.status}`,
        response.status
      );
    }

    const data = await response.json();
    return data;
  } catch (error) {
    if (error instanceof ApiError) {
      console.error(`API Error ${error.statusCode}: ${error.message}`);
    } else if (error instanceof TypeError) {
      console.error('Network error:', error.message);
    } else {
      console.error('Unknown error:', error);
    }
    throw error;
  }
}
```

### Error Recovery Patterns

```typescript
async function fetchWithFallback<T>(
  primaryUrl: string,
  fallbackUrl: string
): Promise<T> {
  try {
    return await fetchWithErrorHandling<T>(primaryUrl);
  } catch (error) {
    console.warn('Primary fetch failed, trying fallback');
    return await fetchWithErrorHandling<T>(fallbackUrl);
  }
}

// Multiple fallbacks
async function fetchWithMultipleFallbacks<T>(
  urls: string[]
): Promise<T> {
  let lastError: Error | undefined;

  for (const url of urls) {
    try {
      return await fetchWithErrorHandling<T>(url);
    } catch (error) {
      lastError = error instanceof Error ? error : new Error(String(error));
      console.warn(`Failed to fetch from ${url}, trying next...`);
    }
  }

  throw new Error(
    `All fetches failed. Last error: ${lastError?.message ?? 'Unknown'}`
  );
}
```

### Typed Error Handling

```typescript
class ValidationError extends Error {
  constructor(message: string, public field: string) {
    super(message);
    this.name = 'ValidationError';
  }
}

class NetworkError extends Error {
  constructor(message: string, public url: string) {
    super(message);
    this.name = 'NetworkError';
  }
}

type AppError = ValidationError | NetworkError | Error;

async function handleUserUpdate(userId: string, data: unknown): Promise<void> {
  try {
    await validateUserData(data);
    await updateUser(userId, data);
  } catch (error) {
    if (error instanceof ValidationError) {
      console.error(`Validation error in field ${error.field}: ${error.message}`);
    } else if (error instanceof NetworkError) {
      console.error(`Network error for ${error.url}: ${error.message}`);
    } else if (error instanceof Error) {
      console.error(`Unexpected error: ${error.message}`);
    }
    throw error;
  }
}
```

## Promise Combinators

### Promise.all

```typescript
interface UserData {
  profile: User;
  posts: Post[];
  comments: Comment[];
}

async function fetchUserDataParallel(userId: string): Promise<UserData> {
  const [profile, posts, comments] = await Promise.all([
    fetchUserData(userId),
    fetchPostsByUser(userId),
    fetchCommentsByUser(userId),
  ]);

  return { profile, posts, comments };
}

// Type-safe Promise.all with tuple
async function fetchMultipleResources() {
  const [users, posts, settings] = await Promise.all([
    fetchUsers(),      // Promise<User[]>
    fetchPosts(),      // Promise<Post[]>
    fetchSettings(),   // Promise<Settings>
  ] as const);

  // TypeScript infers correct types
  const firstUser: User = users[0];
  const firstPost: Post = posts[0];
}
```

### Promise.allSettled

```typescript
interface SettledResult<T> {
  status: 'fulfilled' | 'rejected';
  value?: T;
  reason?: Error;
}

async function fetchAllUserData(
  userIds: string[]
): Promise<Array<SettledResult<User>>> {
  const results = await Promise.allSettled(
    userIds.map((id) => fetchUserData(id))
  );

  return results.map((result) => {
    if (result.status === 'fulfilled') {
      return { status: 'fulfilled', value: result.value };
    } else {
      return { status: 'rejected', reason: result.reason };
 

Related in Writing & Docs