Type vs interface

Sim, é mais um artigo sobre type vs interface, quando usar cada um e etc, mas eu te prometo que esse vai ser diferente de todos que você já viu, exploraremos tópicos básicos (que muitos já sabem) e até os mais avançados (que poucos sabem). Também iremos ir um pouco mais longe e voltar no tempo, assim entenderemos que essa dúvida nem sempre existiu, por pelo menos dois motivos.

O começo de tudo

Um ponto que sempre é importante ao olhar pro typescript é analisar a sua história, muitas pessoas apenas usam features e pensam que aquilo sempre existiu, mas até mesmo as coisas que mais fazem sentido e parecem mais óbvias não existiam até um tempo atrás, e o ponto é justamente esse, a keyword "type" para declaração de tipos foi lançada apenas na versão 1.4 do typescript (6 versões após a primeira versão).

Enquanto isso, interfaces sempre existiram. Você provavelmente sabe que interfaces só podem definir objetos (se não sabe, não tem problema, discorreremos sobre logo logo), sendo assim, como definíamos strings literais, tipos condicionais e etc? Simples, isso nem existia ainda, a criação da keyword type possibilitou a adição de outras várias features.

Esse é o primeiro motivo da dúvida não existir antigamente. E o segundo motivo? Bom, acontece que a ideia era que types fossem usados para definir vários tipos diferentes como tuplas, unions, funções, arrays, e etc, mas NÃO objetos literais (assim como fazemos em interfaces), na primeira implementação da keyword type, usar type para objetos literais geraria uma mensagem de erro.

type User = {
  name: string
  age: number
}
// Error: Aliased type cannot be an object type literal.
// Use an interface declaration instead.

Dessa forma seria tranquilo decidir qual usar ou não, precisa definir objetos? Use interface, pro resto, use type, a ideia por trás disso era justamente evitar confusão, mas isso acabou mudando.

Após investigar, não consegui reproduzir a mensagem de erro acima, então presumo que antes da versão 1.4 ser oficialmente lançada, isso foi removido.

Aliás, aqui está a pull request da implementação da keyword type, bem como a pull request que permite que types sejam usados para definir objetos literais, e também a discussão desse tema. 

Show, entendemos a história por trás disso tudo, mas e agora? Nos sobra uma dúvida, qual usar? O próprio time do typescript documentou algumas diferenças entre type vs interface, mas com certeza não todas elas, agora finalmente entraremos no assunto, explicarei as diferenças, começaremos com as diferenças mais básicas e iremos até as mais avançadas, bora lá?

Interfaces só podem definir objetos, types podem definir qualquer tipo

Essa é uma das principais diferenças, interfaces servem exclusivamente pra declarar objetos, e objetos podem ter métodos e propriedades, já types podem fazer o mesmo, mas também podem definir qualquer outro tipo, como arrays, tuplas, unions, funções, tipos literais, mapped types, e até tipos primitivos como string, number, boolean, Date, etc.

Outro ponto que vale ressalva, é de que até a versão 2.1 do typescript, apenas interfaces e classes poderiam ser usadas como contrato de uma classe através da keyword implements, usar um type geraria um erro.

 type UsersRepository = {
   create: (name: string) => string;
 };
 
 class Users implements UsersRepository {
   create(name: string) {
     return "alv";
   }
 } 
 // Error: A class may only implement another
 // class or interface.

Hover em interface vs em type

A primeira diferença visual que podemos notar é que o hover em interfaces e o hover em type são diferentes, enquanto o hover na interface mostra apenas o nome da interface, em type é mostrado o tipo definido e também o seu nome.

Hover em interface mostra apenas o seu nomeVSHover em type mostra seu nome e também o tipo definido

Criando um tipo usando interface é como se estivéssemos criando um tipo novo, por exemplo, se algo é do tipo String (com letra maiúscula, estamos falando do constructor), o que você verá no hover é apenas o nome String (até mesmo porque String é implementado usando interface) e não todos os métodos e propriedades que String tem.

Já usando type, é como se estivéssemos criando apenas um alias, pra um tipo que pode ser anônimo ou não.

Interfaces podem ser redeclaradas, types não

Lorem, ipsum dolor sit amet consectetur adipisicing elit. Nobis quasi in recusandae fuga doloremque vero, ex beatae odio culpa harum asperiores. Et temporibus commodi error consectetur eligendi placeat nisi. Quibusdam.

Lorem, ipsum dolor sit amet consectetur adipisicing elit. Nobis quasi in recusandae fuga doloremque vero, ex beatae odio culpa harum asperiores. Et temporibus commodi error consectetur eligendi placeat nisi. Quibusdam.

Interfaces não podem estender uma union, mesmo que seja uma union de objetos

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Autem quam totam earum eum, ipsa veritatis odio minima amet enim unde accusamus sequi voluptates sunt nostrum error deleniti ducimus voluptatibus molestias?

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Autem quam totam earum eum, ipsa veritatis odio minima amet enim unde accusamus sequi voluptates sunt nostrum error deleniti ducimus voluptatibus molestias?

Interfaces não podem ser utilizadas para criar tipos derivados

Lorem ipsum dolor sit amet consectetur adipisicing elit. Iusto, saepe magnam. Nesciunt dolores impedit fugiat, voluptate, laudantium recusandae illum laboriosam qui tempore id sed, tenetur harum sequi iste porro ipsam.

Lorem ipsum dolor sit amet consectetur adipisicing elit. Iusto, saepe magnam. Nesciunt dolores impedit fugiat, voluptate, laudantium recusandae illum laboriosam qui tempore id sed, tenetur harum sequi iste porro ipsam.

Interfaces se comportam de maneira diferente de types ao compor objetos

Lorem ipsum dolor sit amet consectetur adipisicing elit. Iusto, saepe magnam. Nesciunt dolores impedit fugiat, voluptate, laudantium recusandae illum laboriosam qui tempore id sed, tenetur harum sequi iste porro ipsam.

Lorem ipsum dolor sit amet consectetur adipisicing elit. Iusto, saepe magnam. Nesciunt dolores impedit fugiat, voluptate, laudantium recusandae illum laboriosam qui tempore id sed, tenetur harum sequi iste porro ipsam.

Types têm assinatura implícita de índice

Lorem ipsum dolor sit amet consectetur adipisicing elit. Iusto, saepe magnam. Nesciunt dolores impedit fugiat, voluptate, laudantium recusandae illum laboriosam qui tempore id sed, tenetur harum sequi iste porro ipsam.

Lorem ipsum dolor sit amet consectetur adipisicing elit. Iusto, saepe magnam. Nesciunt dolores impedit fugiat, voluptate, laudantium recusandae illum laboriosam qui tempore id sed, tenetur harum sequi iste porro ipsam.

Interfaces têm melhor performance do que types ao compor vários objetos

Lorem ipsum dolor sit amet consectetur adipisicing elit. Iusto, saepe magnam. Nesciunt dolores impedit fugiat, voluptate, laudantium recusandae illum laboriosam qui tempore id sed, tenetur harum sequi iste porro ipsam.

Lorem ipsum dolor sit amet consectetur adipisicing elit. Iusto, saepe magnam. Nesciunt dolores impedit fugiat, voluptate, laudantium recusandae illum laboriosam qui tempore id sed, tenetur harum sequi iste porro ipsam.

Interfaces têm "this" e isso possibilita a criação de Higher Kinded Types

Lorem ipsum dolor sit amet consectetur adipisicing elit. Iusto, saepe magnam. Nesciunt dolores impedit fugiat, voluptate, laudantium recusandae illum laboriosam qui tempore id sed, tenetur harum sequi iste porro ipsam.

Lorem ipsum dolor sit amet consectetur adipisicing elit. Iusto, saepe magnam. Nesciunt dolores impedit fugiat, voluptate, laudantium recusandae illum laboriosam qui tempore id sed, tenetur harum sequi iste porro ipsam.