FNSP Web Page

Uniões discriminadas: deixar o compilador contar os casos

Um ecrã que carrega dados tem três estados possíveis, e quase toda a gente os escreve assim:

type Estado = {
  aCarregar: boolean;
  dados?: Artigo[];
  erro?: string;
};

O problema deste tipo é que ele permite coisas impossíveis: aCarregar: true com dados e com erro ao mesmo tempo. Nada no compilador impede essa combinação, e é preciso lembrar-se dela em cada if.

1. Um campo que decide o resto

Uma união discriminada é um conjunto de formas alternativas, cada uma com um campo comum que diz qual delas é:

type Estado =
  | { tipo: 'aCarregar' }
  | { tipo: 'pronto'; artigos: Artigo[] }
  | { tipo: 'erro'; mensagem: string };

Agora os estados impossíveis deixam de se poder escrever, e o TypeScript sabe, dentro de cada ramo, o que existe:

function mostrar(estado: Estado) {
  if (estado.tipo === 'pronto') {
    return estado.artigos.length; // aqui, 'artigos' existe de certeza
  }

  return estado.artigos;
  //            ~~~~~~~ Erro: não existe no estado 'aCarregar' nem em 'erro'
}

2. O truque do never

Esta é a parte que muda a vida. Num switch, atribuir o valor a uma variável do tipo never no ramo final obriga o compilador a confirmar que não sobrou nenhum caso:

function texto(estado: Estado): string {
  switch (estado.tipo) {
    case 'aCarregar':
      return 'A carregar…';
    case 'pronto':
      return `${estado.artigos.length} artigos`;
    case 'erro':
      return estado.mensagem;
    default:
      const naoTratado: never = estado;
      return naoTratado;
  }
}

No dia em que acrescentar um quarto estado ao tipo — { tipo: 'vazio' } — esta função deixa de compilar, com o erro a apontar para o sítio certo:

// Erro: o tipo '{ tipo: "vazio"; }' não é atribuível ao tipo 'never'

É a diferença entre descobrir o caso esquecido no compilador e descobri-lo em produção, num ecrã em branco.

Comentários

Ainda ninguém comentou este artigo.

Voltar ao blog

Gostávamos de saber quantas pessoas visitam o site, com o Google Analytics. Sem a sua autorização não corre nada. Política de Privacidade.