Tratamento de Erros em TypeScript: try/catch, Classes Personalizadas e Tipagem Estrita

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
```html

Introdução: Por que o tratamento de erros em TypeScript não é apenas try/catch

TypeScript adiciona tipagem estática ao JavaScript, mas erros de tempo de execução (runtime errors) continuam sendo parte de qualquer aplicação. Ao contrário do JS puro, onde catch(e) retorna any, o TypeScript oferece mecanismos mais rigorosos. O tratamento adequado de erros não é apenas prevenir crashes, mas também criar um sistema compreensível para depuração e manutenção do código. Neste artigo, abordaremos todos os aspectos: desde o básico try/catch até a criação de hierarquias de erros personalizadas com tipagem completa.

1. Sintaxe básica do try/catch e o problema do tipo unknown

Construção clássica

A construção básica em TypeScript é igual à do JavaScript:

try {
    // Código que pode lançar uma exceção
    const data = JSON.parse('{"name": "TypeScript"}');
    console.log(data.name);
} catch (error) {
    // Tratamento do erro
    console.error('Ocorreu um erro:', error);
}

No entanto, há uma diferença importante: em TypeScript, a variável error no bloco catch tem o tipo unknown (e não any, como em JavaScript, a menos que especificado de outra forma). Isso é feito para segurança de tipos.

O problema com unknown e como resolvê-lo

O tipo unknown significa que não podemos simplesmente acessar as propriedades do erro, por exemplo, error.message. O compilador emitirá um erro:

catch (error) {
    // Erro TS2571: Object is of type 'unknown'.
    console.log(error.message); // ❌ Não compilará
}

Para acessar as propriedades, precisamos restringir o tipo:

catch (error) {
    if (error instanceof Error) {
        console.log(error.message); // ✅ Funciona
    } else {
        console.log('Erro desconhecido:', error);
    }
}

Ou usar uma verificação de existência da propriedade:

catch (error) {
    if (error && typeof error === 'object' && 'message' in error) {
        console.log((error as { message: string }).message);
    }
}

2. Criando classes de erro personalizadas com tipagem

Por que isso é importante?

O Error padrão contém apenas name, message e stack. Em projetos reais, geralmente são necessários campos adicionais: código do erro, status HTTP, dados para logging. O TypeScript permite criar uma hierarquia de classes de erro com suporte total a tipos.

Exemplo de classe personalizada

// Classe base para todos os erros da aplicação
class AppError extends Error {
    public readonly statusCode: number;
    public readonly isOperational: boolean;

    constructor(message: string, statusCode: number = 500, isOperational: boolean = true) {
        super(message);
        this.name = 'AppError';
        this.statusCode = statusCode;
        this.isOperational = isOperational;
        
        // Restaura o protótipo (necessário para TypeScript)
        Object.setPrototypeOf(this, new.target.prototype);
    }
}

// Erros especializados
class NotFoundError extends AppError {
    constructor(resource: string) {
        super(`${resource} não encontrado`, 404);
        this.name = 'NotFoundError';
    }
}

class ValidationError extends AppError {
    public readonly errors: string[];

    constructor(errors: string[]) {
        super('Erro de validação', 400);
        this.name = 'ValidationError';
        this.errors = errors;
    }
}

Uso com try/catch

function getUser(id: number): User {
    if (id <= 0) {
        throw new ValidationError(['ID deve ser um número positivo']);
    }
    // ... lógica para obter o usuário
    if (!user) {
        throw new NotFoundError('Usuário');
    }
    return user;
}

try {
    const user = getUser(-1);
} catch (error) {
    if (err
```                

Blogs

Book Recommendations