logo

Banner do Post

Typescript: interfaces Vs Type

Ao tipar uma função, um objeto ou até mesmo um componente utilizando TypeScript, vocẽ pode se questionar se deve utilizar "type" ou "interface", nesse artigo irei lhe mostrar as diferença que existem entre essas ferramentas e algumas vantágens que o TypeScript pode trazer para os seus projetos.

Introdução

Antes de mais nada, para introdução ao assunto, o TypeScript é uma ferramenta que adiciona tipagem estática ao JavaScript que por padrão é uma linguagem que possui tipagem dinâmica, ou seja, as variáveis e funções podem assumir tipos distintos durante o tempo de execução. Você pode encontrar mais um pouco sobre esse assunto no seguinte artigo:

E Vale lembrar que o código TypeScript é utilizando somente em ambiente de desenvolvimento e é totalmente convertido para JavaScript no processo de build de produção, ou seja, o navegador ou o Node lerão somente código JS no fim das contas.

Conceitos iniciais

Para tipar variáveis, podemos adicionar seu tipo após sua declaração, lembrando que nem todas variáveis precisam tipagem devido a inferência de tipos.

const x: string = "Carlos";

const lista: string[] = ["Carlos", "Eduardo", "Marcos"];

Para tipar os parâmetros de uma função informamos o tipo logo após a declaração do argumento e para o retorno de função adicionamos a tipagem logo após fechar os parênteses dos parâmetros.

function compare (x: number, y: number): string {
  return x > y ? 'X maior que Y' : 'Y maior que X';
}

Type vs Interface

A diferença entre essas duas ferramentas costumava ser mais clara, mas com as últimas versões de TypeScript, elas estão cada vez mais semelhantes, porém, ainda possuindo algumas características próprias. Por exemplo, muitas vezes precisamos reaproveitar tipagens entre vários arquivos e funções da aplicação, nisso entram as interfaces:

interface Pessoa {
  nome: string
  idade: number
}

function Comprimentar (pessoa: Pessoa): string {
  return `Olá, ${pessoa.nome}`;
}

function maiorDeIdade (pessoa: Pessoa): boolean {
  return pessoa.idade >= 18;
}

Quando uma variável pode assumir formatos distintos mesmo que pertencendo a uma mesma entidade podemos utilizar os Types. Esses se diferem das interfaces em alguns pontos como:

  • Interfaces podem herdar outras interfaces, types não.
  • types pode assumir formatos distintos.
type Polygon =
  { type: 'square', x: number } |
  { type: 'circle', radius: number } |
  { type: 'rectangle', x: number, y: number };

export function area (polygon: Polygon): number {}

Veja que no exemplo acima, o parâmetro da função pode assumir três formatos diferentes baseado no tipo de figura geométrica. Nesse contexto, cada uma dessas ferramentas possuem algumas funcionalidades únicas que você irá compreender ao longo desse artigo.

Declaration merging

Essa funcionalidade está presente apenas nas interfaces, que basicamente permite que o Ts misture duas ou mais interfaces que possuem o mesmo nome em apenas uma declaração. Por exemplo, imagina que você tenha duas interfaces chamadas "user":

interface user {
  nome: string
}

interface user {
  lastName: string
}

Ao declarar essa interface a uma constante, o compilador irá juntar os tipos que elas possuem:

const user1: user = {
  name = "Mario",
  lastName = "Teste"
}

Ou seja, o TypeScript, automaticamente faz um merge entre as duas interfaces. Caso tente fazer isso utilizando o type, você obterá um erro.

Extends e implements

No Typescript podemos utilizar o extends e o implements nas interfaces, algo que não é possível ao utilizar o type, ou seja, as interfaces em TypeScript podem extender as classes, este é um conceito muito interessante que ajuda muito ao utilizarmos uma programação mais orientada a objetos ou quando queremos reaproveitar propriedades de tags HTML em componentes JSX.

Por exemplo, imaginemos que temos uma classe chamada Carro e uma interface chamada NewCar, podemos facilmente extender esta classe usando uma interface:

class Car {
  printCar = () => {
    console.log("this is my car")
  }
};

interface NewCar extends Car {
  name: string;
};

class NewestCar implements NewCar {
  name: "Car";
  constructor(engine:string) {
    this.name = name
  }
  printCar = () => {
    console.log("this is my car")
  }
};

Intersection

A intersection nos permite combinar vários type em um só e para fazer isso basta utilizar o &.

type Name = {
  name: “string”
};

type Age = {
  age: number
};

type Person = Name & Age;

Uma fato interessante é que podemos criar um Intersection type ao juntar duas interfaces:

interface Name {
  name: “string”
};

interface Age {
  age: number
};

type Person = Name & Age;

Vantágens do Typescript

Além de ajudar no ambiente de desenvolvimento, o TypeScript ainda permite que utilizemos de funcionalidades da linguagem que ainda não estão disponíveis de forma nativa, por exemplo, no NodeJs podemos utilizar os ES Modules (import/export) normalmente.

Outro ponto bem legal é que podemos transpilar nosso código para que o mesmo seja lido por todas versões de browsers, ou seja, desse modo podemos utilizar TypeScript nas nossas aplicações React.

Conclusão

Espero que você tenha compreendido a diferença entre type e interface, claro que nesse artigo, eu apenas apresentei alguns aspectos e forma bastante resumida, você aprender mais sobre essa ferramenta, ou melhor, linguagem, na própria documentação do TypeScript:

Qualquer dúvida, dicas ou sugestões, não se esqueça de deixar nos comentário aqui em baixo.

Espero que tenha curtido 🤟

Debugando um código NodeJS que está rodando em um servidor Docker no VSCode.

Post anterior

Construindo interfaces declarativas com Chakra UI

Próximo post