Como rejeitar corretamente em async/await? Análise em TypeScript

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Async/Await e reject: por que isso é um problema para iniciantes?

\n

Você já escreveu uma função async, esperou uma resposta do servidor e depois pegou um UnhandledPromiseRejection? Familiar? Este é um dos problemas mais comuns enfrentados por desenvolvedores que estão migrando para async/await no TypeScript.

\n\n

No Stack Overflow, a pergunta "How to reject in async/await syntax?" acumulou milhares de visualizações. E não é à toa. À primeira vista, parece que basta retornar Promise.reject() — e pronto. Mas em projetos reais é mais complexo: tipos, cadeias de chamadas, perda de contexto de erros.

\n\n

Neste guia, vamos analisar como rejeitar promessas corretamente em funções async do TypeScript, aprender a diferenciar throw de return Promise.reject() e ver exemplos práticos de projetos reais.

\n\n

Fundamentos: como funciona o reject em async/await

\n

Antes de mergulhar nos detalhes, vamos relembrar o básico. Qualquer função async no TypeScript retorna uma Promise. Se dentro dela ocorrer um throw ou for retornado Promise.reject(), a promessa entra no estado rejected.

\n\n
// Exemplo simples de reject em async/await\nasync function fetchUser(id: number): Promise<User> {\n    if (id <= 0) {\n        throw new Error('ID de usuário inválido');\n    }\n    // ...lógica para obter o usuário\n}
\n\n

Aqui, throw é automaticamente convertido em reject. Mas e se quisermos retornar uma promessa já rejeitada?

\n\n

throw vs return Promise.reject()

\n

No TypeScript, ambas as abordagens funcionam, mas há nuances:

\n\n
    \n
  • throw — é a forma mais idiomática. Ele interrompe a execução da função e passa o controle para o catch mais próximo.
  • \n
  • return Promise.reject() — retorna explicitamente uma promessa rejeitada. Útil quando você precisa passar um erro de outra função.
  • \n
\n\n
// Diferença entre throw e return Promise.reject()\nasync function processOrder(orderId: string): Promise<OrderStatus> {\n    // Opção 1: throw\n    if (!orderId) {\n        throw new Error('ID do pedido é obrigatório');\n    }\n    \n    // Opção 2: return Promise.reject\n    if (orderId.startsWith('test_')) {\n        return Promise.reject(new Error('Pedidos de teste não são permitidos'));\n    }\n    \n    return { status: 'processing' };\n}
\n\n

Importante: O TypeScript nem sempre infere corretamente os tipos ao usar return Promise.reject(). Se a função espera Promise<T> e você retorna Promise.reject(), pode ocorrer um erro de tipagem. Nesses casos, é melhor usar throw.

\n\n

Erros típicos ao rejeitar em funções async

\n

Mesmo desenvolvedores experientes em TypeScript às vezes cometem erros clássicos. Aqui estão os top 3:

\n\n

1. Esquecer de tratar o reject no código chamador

\n
async function main() {\n    // Ruim: sem try/catch\n    const user = await fetchUser(-1);\n    console.log(user); // UnhandledPromiseRejection!\n}\n\n// Bom:\nasync function mainSafe() {\n    try {\n        const user = await fetchUser(-1);\n        console.log(user);\n    } catch (error) {\n        console.error('Falha ao buscar usuário:', error);\n    }\n}
\n\n

2. Tipagem incorreta de erros

\n

No TypeScript, o bloco catch por padrão captura unknown. Isso é correto, mas às vezes os desenvolvedores tentam acessar error.message sem verificação.

\n\n
try {\n    await riskyOperation();\n} catch (error) {\n    // Erro: error é unknown\n    console.log(error.message); // ❌ A propriedade 'message' não existe no tipo 'unknown'\n    \n    // Correto:\n    if (error instanceof Error) {\n        console.log(error.message);\n    } else {\n        console.log                

Blogs

Book Recommendations