Uniões discriminadas ou Tipos de união marcados - TypeScript Narrowing #4

TypeScript Narrowing #4

Olá! E seja bem-vindo ao quarto artigo em nossa série de narrowing do TypeScript. Estamos continuando de onde paramos, então, se você perdeu algum dos vídeos anteriores, eu sugiro que você volte e leia-os.

Neste artigo, abordaremos os tagged union types (também conhecidos como discriminated unions).

E temos muito mais por vir nos próximos artigos:

  1. Guards de asserção
  2. Guards de ordem superior
  3. Biblioteca Narrowing

Sou Lucas Paganini, e neste site, lançamos tutoriais de desenvolvimento web. Inscreva-se na newsletter se estiver interessado nisso.

LinkTagged Union Types (Uniões Discriminadas)

Então, tagged union types... o que são?

Na verdade, é bem autoexplicativo. Eles são union types com uma tag 😅

Por exemplo, você poderia ter um union type chamado Log, que agrega três interfaces: Warning, Debug e Information.

TypeScript
type Log = Warning | Debug | Information;

interface Warning {
  text: string;
}

interface Debug {
  message: string;
}

interface Information {
  msg: string;
}

Legal, agora temos um union type. Para transformar isso em uma tagged union type, precisamos de uma propriedade comum com tipos literais entre nossas interfaces. Pode ser qualquer nome de propriedade, mas para simular um exemplo real, vamos chamá-lo de .subscribeToTheNewsletter.

Esta propriedade servirá como um ID para as diferentes interfaces que compõem o tipo Log. Cada interface terá um tipo literal diferente nessa propriedade.

TypeScript
type Log = Warning | Debug | Information;

interface Warning {
  subscribeToTheNewsletter: 'like';
  text: string;
}

interface Debug {
  subscribeToTheNewsletter: 'comment';
  message: string;
}

interface Information {
  subscribeToTheNewsletter: 'share';
  msg: string;
}

E é isso. A propriedade .subscribeToTheNewsletter está servindo como uma tag para o tipo Log, então agora ele é um tagged union type.

LinkTerminologia da União Discriminada

Como mencionei antes, isso também é conhecido como discriminated union, e nossa propriedade .subscribeToTheChannel é a propriedade discriminante de Log.

Para citar a documentação do TypeScript: "Quando cada tipo em uma união contém uma propriedade comum com tipos literais, o TypeScript considera isso uma união discriminada."

A partir de agora, usarei a terminologia de "discriminated unions", em vez de "tagged union types" porque esse é o nome usado atualmente e eu quero ser consistente com as terminologias oficiais. Embora eu acredite que "tagged union types" seria um nome melhor.

LinkType Guards para Discriminated Unions

"Ok Lucas, entendi. Mas de que adianta? O que eu ganho com um discriminated union?"

Boa pergunta.

Você ganha um type guard para todas as discriminações possíveis do seu tipo.

Por exemplo, se você tiver uma variável chamada value, que é um Log. Isso significa que value pode ser um Warning, um Debug ou uma Information.

TypeScript
let value: Log;

if (isWarning(value)) {
  // Handle the Warning case
} else if (isDebug(value)) {
  // Handle the Debug case
} else if (isInformation(value)) {
  // Handle the Information case
}

const isWarning =
  (value: unknown): value is Warning => { ... }

const isDebug =
  (value: unknown): value is Debug => { ... }

const isInformation =
  (value: unknown): value is Information => { ... }

Mas ao invés de criar type guards separadas para cada uma dessas três interfaces, você poderia apenas verificar o valor da propriedade discriminante.

Se .subscribeToTheNewsletter é "like", você sabe que é um Warning. Se for um "comment", é um Debug. E se for "share", é uma Information.

TypeScript
let value: Log;

if (value.subscribeToTheNewsletter === 'like') {
  // Handle the Warning case
} else if (value.subscribeToTheNewsletter === 'comment') {
  // Handle the Debug case
} else if (value.subscribeToTheNewsletter === 'share') {
  // Handle the Information case
}

E você pode tornar seu código ainda mais claro "switching" (trocando) as suas declarações if. Entendeu? 😉 "switching"... "switch"... Não? Ok...

TypeScript
let value: Log;

switch (value.subscribeToTheNewsletter) {
  case 'like':
  // Handle the Warning case
  case 'comment':
  // Handle the Debug case
  case 'share':
  // Handle the Information case
}

LinkConclusão

Referências e links para os vídeos anteriores estão abaixo.

Se você gostou do conteúdo, já sabe o que fazer.

E se a sua empresa está procurando desenvolvedores web remotos, considere entrar em contato comigo e com a minha equipe. Você pode fazer isso em lucaspaganini.com.

Tenha um ótimo dia e nos vemos em breve.

LinkConteúdo Relacionado

  1. TypeScript Narrowing Parte 1 - O que é um Type Guard
  2. TypeScript Narrowing Parte 2 - Type Guards Fundamentais
  3. TypeScript Narrowing Parte 3 - Type Guards Customizados

LinkReferências

  1. Narrowing Documentação do TypeScript
  2. Discriminated Unions Documentação do TypeScript

Assine a nossa Newsletter e seja avisado quando eu lançar um curso, postar um vídeo ou escrever um artigo.

Campo obrigatório
Campo obrigatório