Diga adeus ao try/catch. Use to() no seu código assíncrono.

Diga adeus ao try/catch. Use to() no seu código assíncrono.
Diga adeus ao try/catch. Use to() no seu código assíncrono.

Se você já se pegou escrevendo vários blocos try/catch em código assíncrono, sabe como isso rapidamente vira um caos. Felizmente, existe uma abordagem mais elegante para tratar erros em Promises: a função to().

Hoje vou te mostrar como usar essa função simples para deixar seu código limpo, funcional e mais legível. Ideal para APIs, fetch e qualquer Promise que possa falhar.

O problema com try/catch em Promises

async function carregarUsuario() {
  try {
    const res = await fetch('/api/user');
    const json = await res.json();
    console.log(json);
  } catch (err) {
    console.error('Erro ao buscar usuário:', err);
  }
}

Esse padrão é funcional, mas se você tiver mais de uma Promise, vai precisar de try/catch aninhado ou separar demais a lógica. Fica verboso, difícil de manter e de testar.

A função to()

export async function to<T>(promise: Promise<T>): Promise<[Error | null, T | null]> {
  try {
    const data = await promise;
    return [null, data];
  } catch (err) {
    return [err as Error, null];
  }
}

Simples: ela embrulha uma Promise e sempre retorna um array com [erro, resultado].

Exemplo com fetch

import { to } from './utils/to';

async function buscarProduto(id: string) {
  const [errRes, res] = await to(fetch(`/api/produtos/${id}`));
  if (errRes) return console.error('Erro de rede:', errRes);

  const [errJson, data] = await to(res!.json());
  if (errJson) return console.error('Erro no JSON:', errJson);

  console.log('Produto carregado:', data);
}

Sem try, sem catch, e a lógica continua fluindo. O código fica mais funcional e fácil de testar por partes.

Vantagens

  • ✅ Sem repetição de try/catch
  • ✅ Padroniza o tratamento de erro
  • ✅ Ideal para múltiplas Promises em sequência
  • ✅ Fica mais legível e com menos indentação

Crie um hook customizado

Se estiver em um projeto React, pode até criar um hook com to() para chamadas API:

export function useSafeFetch<T>() {
  return async (url: string): Promise<[Error | null, T | null]> => {
    const [err, res] = await to(fetch(url));
    if (err) return [err, null];
    const [parseErr, data] = await to<T>(res!.json());
    return [parseErr, data];
  };
}

A função to() não é mágica — ela é apenas uma forma inteligente de estruturar código assíncrono de forma limpa e previsível. Você pode usá-la em qualquer projeto Node, React, Next.js ou qualquer app com Promises.

Adote esse padrão e nunca mais sofra com blocos infinitos de try/catch.