Types vs Interfaces no TypeScript: Diferenças, Semelhanças e Quando Usar Cada Um.

No TypeScript, temos duas opções para definir tipos: types (tipos) e interfaces. Uma dúvida muito comum é qual delas devemos usar.

A resposta, como muitas em programação, é: depende. Em alguns casos, uma pode ser claramente mais adequada que a outra, mas em muitos outros, elas são intercambiáveis.

Neste artigo, vamos explorar as principais diferenças e semelhanças entre types e interfaces e quando é mais apropriado usar cada uma.

O básico sobre tipos e interfaces

Tipos e “type aliases” (apelidos de tipo)

No TypeScript, type é uma palavra-chave usada para definir a estrutura dos dados. Alguns tipos básicos incluem:

  • String (texto)
  • Boolean (verdadeiro ou falso)
  • Number (números)
  • Array (listas)
  • Tuple (tuplas)
  • Enum (enumerações)

Esses tipos servem para diferentes finalidades, e você pode escolher o que se encaixa melhor no seu caso.

Um type alias é basicamente um nome alternativo para um tipo já existente. Ele não cria um novo tipo, mas fornece um jeito mais fácil de se referir a um tipo.

Exemplo:

type MeuNumero = number;
type Usuario = {
  id: number;
  nome: string;
  email: string;
};

Aqui, criamos dois aliases: um para números e outro para representar um usuário.

Interfaces no TypeScript

Já uma interface define um “contrato” que um objeto precisa seguir. Veja o exemplo:

interface Cliente {
  nome: string;
  endereco: string;
}

Este contrato exige que todo objeto do tipo Cliente tenha as propriedades nome e endereco. Podemos expressar a mesma ideia usando um type:

type Cliente = {
  nome: string;
  endereco: string;
};

Diferenças entre tipos e interfaces

Agora que vimos que ambos podem ser usados para definir estruturas, é importante entender as diferenças. Há casos em que type ou interface fazem mais sentido. Vamos ver alguns exemplos.

Tipos primitivos

Tipos primitivos, como string, number, boolean, null, e undefined, são embutidos no TypeScript. Podemos criar aliases para esses tipos com type, mas interfaces não podem ser usadas para isso.

Exemplo:

type Endereco = string;

Tipos de união

Um tipo de união permite que um valor seja de vários tipos:

type Transporte = 'Carro' | 'Bicicleta' | 'Ônibus' | 'A pé';

As uniões só podem ser definidas com type. Interfaces não têm essa capacidade.

Tipos de funções

Tanto types quanto interfaces podem ser usados para definir o tipo de uma função, mas o type tem uma sintaxe mais concisa:

type Soma = (a: number, b: number) => number;

Com interface:

interface Soma {
  (a: number, b: number): number;
}

No geral, type é preferido aqui por ser mais curto e direto.

Vantagens específicas das interfaces

Uma das funcionalidades exclusivas das interfaces é o merging de declarações. Isso significa que podemos declarar uma mesma interface várias vezes, e o TypeScript automaticamente une todas as declarações.

Exemplo:

interface Cliente {
  nome: string;
}

interface Cliente {
  idade: number;
}

const cliente: Cliente = {
  nome: 'João',
  idade: 30
};

Já com types, isso não é possível. Se tentarmos declarar um type mais de uma vez, ocorrerá um erro.

Extensão: Interfaces vs. Types

Uma interface pode ser estendida para herdar propriedades de outra interface:

interface ClienteVIP extends Cliente {
  beneficios: string[];
}

Para fazer algo similar com types, usamos o operador de interseção (&):

type ClienteVIP = Cliente & { beneficios: string[] };

Ambos podem ser estendidos, mas interfaces costumam ser mais claras, especialmente em grandes projetos.

Conflitos ao estender

Outro ponto importante é como conflitos são tratados. Ao estender interfaces, não podemos usar o mesmo nome de propriedade duas vezes:

interface Pessoa {
  getPermissao: () => string;
}

interface Funcionario extends Pessoa {
  getPermissao: () => string[];
}
// Erro: conflito de tipos

Com types, a abordagem é diferente: eles mesclam as propriedades em vez de gerar erro, o que pode ser útil em alguns casos:

type Pessoa = {
  getPermissao: (id: string) => string;
};

type Funcionario = Pessoa & {
  getPermissao: (id: string[]) => string[];
};

Quando usar types vs interfaces

As interfaces são ideais quando precisamos de declaration merging ou quando seguimos um estilo mais orientado a objetos. Além disso, o TypeScript costuma ser mais eficiente ao trabalhar com interfaces, já que ele armazena em cache as relações entre elas.

Por outro lado, os types são mais flexíveis e poderosos, especialmente quando precisamos de recursos avançados como tipos condicionais, uniões e interseções. Eles também são mais adequados para sobrecarga de funções e manipulação de tipos complexos.

Conclusão

Tipos e interfaces são ferramentas essenciais no TypeScript, e ambos têm suas vantagens. A escolha entre eles depende muito do caso de uso específico e das preferências pessoais. No geral, types são mais versáteis e expressivos, mas interfaces oferecem algumas vantagens de performance e legibilidade em projetos maiores. A chave é entender as diferenças e saber quando usar cada um.


Se você tiver dúvidas ou preferências, sinta-se à vontade para compartilhar nos comentários!

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *