TypeScript: Tratamento de erros no TypeScript

Última atualização: 2026-08-26

O tratamento de erros é uma parte essencial de qualquer projeto — o sistema de tipos do TypeScript torna o tratamento de erros mais seguro e previsível.

1. Noções básicas sobre o tratamento de erros em JavaScript

(1) try/catch/finally

TYPESCRIPT
try {
  let data = JSON.parse(input);
  console.log(data);
} catch (error) {
  // error The type is unknown(strict In mode)
  console.log("Parsing Failed");
} finally {
  console.log("Free Up Resources");
  // This will be executed regardless of success or failure
}

(2) instrução throw

O JavaScript pode lançar qualquer valor — não apenas objetos Error:

TYPESCRIPT
throw new Error("An error occurred");        // ✅ Standard Practice
throw "An error occurred";                    // ⚠️ It's possible, but not ideal.
throw 404;                         // ⚠️ It's possible, but not ideal.
throw { code: 500, msg: "Server Error" }; // ⚠️ It's possible, but not ideal.
📌 Recomendação: Sempre lance um objeto Error (ou uma de suas subclasses) — ele contém informações da pilha de chamadas, o que facilita a depuração. Lançar uma string ou um número não fornece informações da pilha de chamadas.

(3) Tipos de erros

TYPESCRIPT
interface Error {
  name: string;     // Error name (e.g., "TypeError", "RangeError")
  message: string;  // Error Description
  stack?: string;   // Call Stack(Non-standard but widely supported)
}


2. Tipos de erro embutidos e restrição de tipos

(1) Erros comuns de fábrica

Tipo de erro Causado por
Error Erro geral
TypeError Erro de digitação (por exemplo, null.toString())
RangeError Valor fora do intervalo (por exemplo, estouro recursivo)
SyntaxError Erro de sintaxe (por exemplo, falha no JSON.parse)
ReferenceError Referência a uma variável não definida
URIError Erro de codificação/decodificação de URI

(2) Reduzindo os tipos de erros com instanceof

TYPESCRIPT
function processValue(value: unknown) {
  try {
    let num = Number(value);
    if (isNaN(num)) throw new TypeError("Not a valid number");
    if (num < 0) throw new RangeError("Cannot be a negative number");
    return num;
  } catch (error) {
    if (error instanceof TypeError) {
      console.log(`Type error:${error.message}`);  // ✅ narrowed to TypeError
    } else if (error instanceof RangeError) {
      console.log(`Range error:${error.message}`);  // ✅ narrowed to RangeError
    } else if (error instanceof Error) {
      console.log(`Other Errors:${error.message}`);  // ✅ narrowed to Error
    } else {
      // In theory, it won't reach there.——JavaScript Always throw Error or its subclasses
      console.log("Unknown error");
    }
  }
}


3. Classes de erro personalizadas

(1) Erros personalizados básicos

TYPESCRIPT
class AppError extends Error {
  constructor(message: string) {
    super(message);
    this.name = "AppError";  // Incorrect setting name
  }
}

class ValidationError extends AppError {
  constructor(
    message: string,
    public field: string    // Additional error messages
  ) {
    super(message);
    this.name = "ValidationError";
  }
}

class NotFoundError extends AppError {
  constructor(
    public resource: string,
    public id: number | string
  ) {
    super(`${resource} (${id}) Does not exist`);
    this.name = "NotFoundError";
  }
}

(2) Como usar erros personalizados

TYPESCRIPT
function findUser(id: number) {
  if (id <= 0) {
    throw new ValidationError("IDMust be a positive number", "id");
  }
  // Simulated Search
  if (id > 100) {
    throw new NotFoundError("User", id);
  }
  return { id, name: "User" + id };
}

try {
  let user = findUser(999);
} catch (error) {
  if (error instanceof ValidationError) {
    console.log(`Verification Failed:Field ${error.field},${error.message}`);
  } else if (error instanceof NotFoundError) {
    console.log(`Not found:${error.resource},ID=${error.id}`);
  } else if (error instanceof Error) {
    console.log(`Error:${error.message}`);
  }
}

▶ Exemplo: Sistema de erros HTTP

TYPESCRIPT 📖 Somente leitura
class HttpError extends Error {
  constructor(
    public statusCode: number,
    message: string
  ) {
    super(message);
    this.name = "HttpError";
  }
}

class BadRequestError extends HttpError {
  constructor(message: string) {
    super(400, message);
    this.name = "BadRequestError";
  }
}

class UnauthorizedError extends HttpError {
  constructor(message: string = "Unauthorized") {
    super(401, message);
    this.name = "UnauthorizedError";
  }
}

class ForbiddenError extends HttpError {
  constructor(message: string = "Access Denied") {
    super(403, message);
    this.name = "ForbiddenError";
  }
}

class NotFoundError2 extends HttpError {
  constructor(resource: string) {
    super(404, `${resource} Does not exist`);
    this.name = "NotFoundError";
  }
}

// Usage
function handleRequest(path: string) {
  if (!path.startsWith("/api/")) {
    throw new BadRequestError("The path must begin with /api/ Introduction");
  }
  if (path === "/api/admin") {
    throw new ForbiddenError();
  }
  return { data: "Response Data" };
}

try {
  let result = handleRequest("/api/users");
  console.log(result.data);
} catch (error) {
  if (error instanceof HttpError) {
    console.log(`HTTP ${error.statusCode}: ${error.message}`);
  }
}
50 linhas de lógica (limite de 40, somente leitura)

Saída:

TEXT 📖 Somente leitura
Response Data


4. Padrão de resultados

O problema com o try/catch é que “as exceções são implícitas” — a assinatura da função não indica que ela pode lançar uma exceção. O padrão Result torna os erros parte do valor de retorno:

(1) Definir o tipo de resultado

TYPESCRIPT
type Success<T> = { ok: true; value: T };
type Failure<E> = { ok: false; error: E };
type Result<T, E = Error> = Success<T> | Failure<E>;

(2) Criar resultado

TYPESCRIPT
function success<T>(value: T): Success<T> {
  return { ok: true, value };
}

function failure<E>(error: E): Failure<E> {
  return { ok: false, error };
}

(3) Usando Result em vez de try/catch

TYPESCRIPT
function divide(a: number, b: number): Result<number, string> {
  if (b === 0) {
    return failure("The divisor cannot be zero.");
  }
  return success(a / b);
}

let result1 = divide(10, 2);
let result2 = divide(10, 0);

if (result1.ok) {
  console.log(result1.value);  // 5 ✅
} else {
  console.log(result1.error);
}

if (result2.ok) {
  console.log(result2.value);
} else {
  console.log(result2.error);  // "The divisor cannot be zero." ✅
}

(4) Resultado: Métodos baseados em ferramentas

TYPESCRIPT
function tryCatch<T>(fn: () => T): Result<T, Error> {
  try {
    return success(fn());
  } catch (error) {
    return failure(error instanceof Error ? error : new Error(String(error)));
  }
}

async function tryAsync<T>(fn: () => Promise<T>): Promise<Result<T, Error>> {
  try {
    return success(await fn());
  } catch (error) {
    return failure(error instanceof Error ? error : new Error(String(error)));
  }
}

// Usage
let parseResult = tryCatch(() => JSON.parse('{"name":"Charlie"}'));
if (parseResult.ok) {
  console.log(parseResult.value.name);  // "Charlie"
}


5. Tratamento dos tipos de erro no bloco catch

(1) No modo estrito, o erro é desconhecido

TYPESCRIPT
try {
  JSON.parse("invalid");
} catch (error) {
  // error The type is unknown(TypeScript 4.4+)
  // console.log(error.message);  // ❌ unknown NonemessageProperties

  // ✅ Method 1:instanceof Inspection
  if (error instanceof Error) {
    console.log(error.message);
  }

  // ✅ Method 2:Type Assertion(Caution)
  let msg = (error as Error).message;

  // ✅ Method 3:Type Guard Function
  function getErrorMessage(error: unknown): string {
    if (error instanceof Error) return error.message;
    if (typeof error === "string") return error;
    return "Unknown error";
  }
  console.log(getErrorMessage(error));
}

(2) O tipo error em versões mais antigas do TypeScript

TYPESCRIPT
// TypeScript 4.3 and earlier——catch 's error The type is any
// You can tsconfig Useful useUnknownInCatchVariables: true Change to unknown

// TypeScript 4.4+——Default unknown(strict In mode)


▶ Exemplo: Estreitando tipos de erro unknown

Saída:

TEXT 📖 Somente leitura
Division by zero
TYPESCRIPT
function safeReadFile(path: string): string | null {
  try {
    let content = "[simulated file content]";
    if (Math.random() > 0.5) throw new SyntaxError("Parse error");
    return content;
  } catch (error: unknown) {
    if (error instanceof SyntaxError) {
      console.log(`Syntax issue: ${error.message}`);
    } else if (error instanceof Error) {
      console.log(`Error: ${error.message}`);
    } else {
      console.log("Unknown error occurred");
    }
    return null;
  }
}

let data = safeReadFile("config.json");

Saída:

TEXT 📖 Somente leitura
Division by zero

▶ Exemplo: Guarda de tipo para tratamento de erros

Saída:

TEXT 📖 Somente leitura
Division by zero
TYPESCRIPT
function isError(value: unknown): value is Error {
  return value instanceof Error;
}

function getErrorMessage(error: unknown): string {
  if (isError(error)) return error.message;
  if (typeof error === "string") return error;
  if (typeof error === "number") return `Error code: ${error}`;
  return "An unknown error occurred";
}

type AppResult<T> = { ok: true; value: T } | { ok: false; error: string };

function divide(a: number, b: number): AppResult<number> {
  if (b === 0) return { ok: false, error: "Division by zero" };
  return { ok: true, value: a / b };
}

let r = divide(10, 0);
if (!r.ok) console.log(getErrorMessage(r.error)); // Division by zero

Saída:

TEXT 📖 Somente leitura
Division by zero

❓ Perguntas Frequentes

P: O que devo usar, try/catch ou o padrão Result? R: As duas abordagens não são mutuamente exclusivas. try/catch é o mecanismo padrão de tratamento de exceções em JavaScript/TypeScript — adequado para erros imprevisíveis em tempo de execução (como falhas de rede ou problemas de análise de JSON). O padrão Result é adequado para erros de negócio previsíveis — a assinatura da função declara explicitamente que “é possível ocorrer uma falha”, e quem chama a função deve lidar com ela. Basta manter um estilo consistente em todo o seu projeto.

P: Por que o erro é interceptado por catch unknown em vez de Error? R: Porque o JavaScript permite que qualquer valor seja lançado — tanto throw "message" quanto throw 42 são válidos. O TypeScript não pode garantir que o valor capturado por catch seja uma instância de Error; portanto, usar unknown é a abordagem mais segura. No desenvolvimento prático, 99% dos erros lançados são objetos Error — você pode restringir a captura usando instanceof Error.

P: Uma classe de erro personalizada precisa chamar super? R: Sim, precisa. Quando uma classe de erro personalizada herda de Error, ela deve chamar super(message) no construtor para inicializar a propriedade message de Error. Também é recomendável definir this.name manualmente — caso contrário, name assumirá por padrão o nome da classe pai.

P: O código no bloco finally afeta o valor de retorno? R: Uma instrução return no bloco finally substitui a instrução return no bloco try/catch — essa é uma fonte comum de erros. Recomenda-se usar o bloco finally apenas para limpeza de recursos (fechar arquivos, liberar bloqueios etc.) e não incluir instruções return nesse bloco.

📖 Resumo

📝 Exercícios

  1. Problema básico (Dificuldade ⭐): Escreva uma função safeParse(json: string): Result<object, Error> que envolva JSON.parse em um bloco try/catch e retorne success em caso de sucesso e failure em caso de falha.
  2. Problema avançado (Dificuldade ⭐⭐): Defina a classe base AppError e as subclasses DatabaseError (com uma propriedade query) e AuthError (com uma propriedade statusCode). Escreva uma função que retorne diferentes códigos de status HTTP e mensagens com base no tipo de erro.
  3. Desafio (Dificuldade: ⭐⭐⭐): Implemente tryAsync<T>(fn: () => Promise<T>): Promise<Result<T, AppError>> para converter uniformemente as exceções de operações assíncronas no sistema AppError (distinguindo entre erros de rede, erros de tempo limite e erros de servidor). Escreva uma função fetchWithRetry que tente novamente automaticamente em caso de falha.
Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%