Médio TypeScript

Tratamento de erros tipados com classe personalizada

Enunciado

Crie uma classe NotFoundError que estende Error. Implemente uma função async findItem(id: number): Promise<string> que lança NotFoundError se id for maior que 100, e retorna "Item [id]" caso contrário. No bloco catch, trate especificamente NotFoundError e outros erros separadamente.

Requisitos

  • A classe NotFoundError deve ter name = "NotFoundError" e uma mensagem personalizada.
  • A função findItem deve ser async e retornar Promise<string>.
  • O catch deve verificar instanceof NotFoundError e exibir mensagem adequada.
  • Para outros erros, exibir uma mensagem genérica.

Código inicial

class NotFoundError extends Error {
  // complete
}

async function findItem(id: number): Promise<string> {
  // complete
}

async function main() {
  // teste com id válido e inválido
}

main();

Saída esperada

Item 42
Erro: Item 200 não encontrado
Ver dica

No catch, use error instanceof NotFoundError para diferenciar. Lembre-se de que error é unknown por padrão.

Mostrar solução
class NotFoundError extends Error {
  constructor(message: string) {
    super(message);
    this.name = "NotFoundError";
  }
}

async function findItem(id: number): Promise<string> {
  if (id > 100) {
    throw new NotFoundError(`Item ${id} não encontrado`);
  }
  // Simula busca assíncrona
  await new Promise((resolve) => setTimeout(resolve, 50));
  return `Item ${id}`;
}

async function main(): Promise<void> {
  try {
    const item = await findItem(42);
    console.log(item);

    await findItem(200); // lança NotFoundError
  } catch (error: unknown) {
    if (error instanceof NotFoundError) {
      console.error(`Erro: ${error.message}`);
    } else {
      console.error("Erro inesperado:", error);
    }
  }
}

main();

Passo a passo

  1. Definimos NotFoundError estendendo Error e configuramos name para identificação.
  2. findItem verifica se id > 100 e lança NotFoundError com mensagem personalizada.
  3. Se o id for válido, aguardamos 50ms e retornamos a string.
  4. No main, chamamos findItem(42) e imprimimos o resultado.
  5. Chamamos findItem(200) dentro do mesmo try, o que dispara o erro.
  6. No catch, usamos instanceof NotFoundError para tratar especificamente esse erro e exibir a mensagem.
  7. Caso seja outro erro, exibimos uma mensagem genérica.

Por que funciona

O try/catch captura erros lançados por funções assíncronas quando usamos await. Como error é unknown, precisamos de um type guard (instanceof) para acessar message com segurança. A classe personalizada permite distinguir erros de domínio de erros inesperados, mantendo o código robusto e legível.

Erros comuns

  • Não estender Error corretamente: class NotFoundError { ... } não será capturado como erro.
  • Esquecer this.name = "NotFoundError" — a propriedade name fica como "Error", dificultando a identificação.
  • Acessar error.message sem verificar o tipo: console.log(error.message) gera erro de compilação porque error é unknown.
  • Não usar await ao chamar findItem(200): o erro não será capturado pelo try/catch e se tornará uma rejeição não tratada.

Outra forma de resolver

Usar uma união discriminada de erros em vez de classes:

type AppError = { type: "not_found"; message: string } | { type: "unknown"; error: unknown };

Essa abordagem é preferível quando você quer evitar classes e prefere tipos puramente estruturais.

Saída esperada

Item 42
Erro: Item 200 não encontrado