logo hsb.horse
← Voltar para o índice de snippets

Snippets

Implementando um Tipo Result Leve em TypeScript

Um padrão de tratamento de erros sem try-catch. Trate erros de forma type-safe com um tipo Result que separa data e error.

Publicado: Atualizado:

O tratamento de erros para operações assíncronas é frequentemente escrito com try-catch, mas o local onde as exceções ocorrem e o local onde são tratadas tendem a divergir. Com o padrão do tipo Result, você pode separar explicitamente sucesso e falha como valores de retorno.

Pré-requisito: Conversão para o Tipo Error

Um helper para converter de forma confiável erros do tipo unknown para o tipo Error.

export function toError(error: unknown): Error {
if (error instanceof Error) return error;
return new Error(error as never);
}

Definição do Tipo Result

interface Failure {
data: undefined;
error: Error;
}
interface Success<T> {
data: T;
error: undefined;
}
type Result<T> = Success<T> | Failure;

Exemplo de Implementação do Wrapper fetch

import { toError } from './toError.js'
export async function fetcher<T>(
url: RequestInfo,
init?: RequestInit
): Promise<Result<T>> {
const UNDEF = undefined;
// Quando fetch falha (erros de rede, etc.)
const response = await fetch(url, init).catch(toError);
if (response instanceof Error) {
return { data: UNDEF, error: response };
}
// Respostas de erro HTTP
if (!response.ok) {
return {
data: UNDEF,
error: new Error(`HTTP ${response.status}: ${response.statusText}`)
};
}
// Sucesso
const data = await response.json();
return { data, error: UNDEF };
}

Exemplo de Uso

const result = await fetcher<User>("/api/user/123");
if (result.error) {
console.error("Falha ao buscar:", result.error.message);
return;
}
// Quando result.error é undefined, TypeScript infere result.data como T
console.log(result.data.name);

Benefícios e Considerações

Benefícios:

  • Sucesso e falha ficam claros pelo tipo de retorno
  • Menos blocos try-catch melhoram a legibilidade
  • O tratamento de erros pode ser forçado (omissão causa erros de tipo)

Considerações:

  • Se a proposta ECMAScript Safe Assignment Operator for padronizada, funcionalidade similar integrada pode se tornar disponível
  • Não é tão completo quanto os tipos Result embutidos na linguagem de Go ou Rust
  • Tratamento detalhado de erros como erros de validação requer implementação separada

A implementação é simples, mas é eficaz quando você deseja tratar erros de forma type-safe em projetos de pequena escala.