
Interface vs type no TypeScript é uma das dúvidas mais comuns entre desenvolvedores que começam a trabalhar com tipagem estática em projetos JavaScript. Embora interface e type possam definir estruturas de objetos de maneira muito semelhante, cada recurso possui características próprias que se tornam importantes conforme a aplicação cresce. Interfaces são especialmente úteis para representar contratos, objetos e estruturas extensíveis, enquanto aliases criados com type oferecem maior flexibilidade para unions, intersections, tuplas e combinações de tipos. Entender essas diferenças ajuda a escrever código mais legível, previsível e fácil de manter. Neste artigo, você verá exemplos práticos de interface e type, entenderá suas principais diferenças e aprenderá como escolher a melhor abordagem em projetos reais com TypeScript e React.
O que são interface e type no TypeScript?
No TypeScript, tanto interface quanto type podem ser utilizados para descrever a estrutura de um objeto. Isso significa que ambos conseguem definir quais propriedades devem existir, quais são seus respectivos tipos e quais campos podem ser opcionais. Em situações simples, o resultado prático pode ser praticamente idêntico.
Com uma interface, por exemplo, podemos representar um usuário desta maneira:
interface User {
name: string;
age: number;
}
const user: User = {
name: "Samuel",
age: 27
};
A mesma estrutura pode ser criada utilizando type:
type User = {
name: string;
age: number;
};
const user: User = {
name: "Samuel",
age: 27
};
Então, se os dois conseguem representar objetos, qual é realmente a diferença? A resposta está nos recursos disponíveis para extensão, composição e reutilização de tipos. É justamente nesses cenários que cada abordagem começa a demonstrar suas particularidades.
Quando usar interface e como funciona o extends
A interface é uma excelente opção quando o objetivo principal é modelar objetos, entidades e contratos. Ela é muito utilizada para definir estruturas previsíveis que podem ser compartilhadas entre diferentes partes de uma aplicação. Em projetos orientados a objetos ou aplicações React, esse recurso aparece com bastante frequência.
Uma vantagem importante é a possibilidade de utilizar extends. Imagine que sua aplicação possui uma estrutura genérica para representar uma pessoa:
interface Person {
name: string;
}
interface Developer extends Person {
technologies: string[];
}
A interface Developer passa automaticamente a possuir a propriedade name definida em Person, além de suas próprias propriedades:
const developer: Developer = {
name: "Samuel",
technologies: ["React", "TypeScript", "Node.js"]
};
Essa característica ajuda a criar contratos reutilizáveis e torna relações entre estruturas mais explícitas. Por isso, interfaces são frequentemente escolhidas para entidades, modelos e props de componentes, especialmente quando existe a possibilidade de extensão futura.
Declaration Merging: uma diferença importante da interface
Uma característica específica de interface é o chamado Declaration Merging, ou combinação de declarações. O TypeScript permite declarar duas interfaces com o mesmo nome dentro de um contexto compatível e combina suas propriedades automaticamente.
Veja este exemplo:
interface User {
name: string;
}
interface User {
age: number;
}
Para o TypeScript, o resultado será equivalente a:
interface User {
name: string;
age: number;
}
Esse comportamento é especialmente útil na extensão de bibliotecas, declarações globais e APIs que precisam permitir customizações. Com type, isso não acontece. Se você declarar dois aliases com o mesmo nome no mesmo escopo, o TypeScript apresentará um erro.
type User = {
name: string;
};
type User = {
age: number;
};
Portanto, se o projeto depende da possibilidade de ampliar declarações existentes, a interface pode oferecer uma vantagem relevante.
Quando type é melhor: unions, intersections e tuplas
Enquanto a interface possui uma forte relação com estruturas de objetos, o type é mais flexível para representar diferentes categorias de tipos. Ele pode criar aliases para valores primitivos, unions, intersections, funções, tuplas e diversas combinações mais avançadas.
Um dos exemplos mais comuns é o uso de Union Types. Imagine que uma variável de status possa possuir somente três valores:
type Status = "loading" | "success" | "error";
let status: Status = "loading";
status = "success";
Se tentarmos atribuir qualquer outro valor, o TypeScript identificará o problema durante o desenvolvimento:
status = "banana";
O type também permite criar aliases reutilizáveis para múltiplos formatos:
type ID = string | number;
const firstId: ID = 10;
const secondId: ID = "abc123";
Outro recurso bastante utilizado são as tuplas, que permitem controlar tanto o tipo quanto a posição dos elementos:
type Coordinates = [number, number];
const location: Coordinates = [-3.119, -60.021];
Também podemos combinar estruturas utilizando Intersection Types com o operador &:
type Person = {
name: string;
};
type Employee = Person & {
salary: number;
};
const employee: Employee = {
name: "Samuel",
salary: 5000
};
Por isso, quando você precisa de composição de tipos, valores literais ou estruturas mais complexas, o type normalmente oferece uma sintaxe mais natural e poderosa.
Interface ou type em projetos React e aplicações reais?
Em projetos profissionais, não existe obrigação de escolher apenas uma das duas abordagens. interface e type podem coexistir perfeitamente dentro da mesma aplicação. A escolha deve considerar principalmente a intenção daquele tipo e os padrões adotados pela equipe.
Em React com TypeScript, por exemplo, é comum encontrar interfaces utilizadas para representar props:
interface CardProps {
title: string;
description: string;
status: CardStatus;
}
Enquanto o estado ou conjunto de valores possíveis pode ser representado com type:
type CardStatus = "active" | "inactive";
Essa combinação cria um código bastante legível. A interface representa o contrato do componente, enquanto o alias representa um conjunto específico de possibilidades.
Uma regra prática pode ajudar na escolha:
- Use interface quando estiver modelando objetos, contratos, entidades ou estruturas que poderão ser estendidas.
- Use type para unions, intersections, tuplas, aliases, valores literais e composições mais complexas.
- Mantenha consistência com os padrões já utilizados pelo projeto e pela equipe.
Isso significa que usar type para objetos está errado? Não. Da mesma forma, utilizar interface para props do React não é uma regra obrigatória. A legibilidade e a consistência do projeto são mais importantes do que tentar estabelecer um vencedor absoluto.
Perguntas frequentes sobre interface vs type
Interface é melhor que type no TypeScript?
Não existe uma opção universalmente melhor. interface possui vantagens para contratos extensíveis e Declaration Merging, enquanto type possui maior flexibilidade para unions, tuplas, intersections e aliases. A melhor escolha depende do contexto.
Posso utilizar type para props do React?
Sim. Tanto type quanto interface podem definir props de componentes React. Muitas equipes utilizam interfaces por convenção, mas um alias de tipo funciona perfeitamente na maioria desses cenários.
É errado utilizar interface e type no mesmo projeto?
Não. Na verdade, utilizar os dois pode tornar o código mais expressivo. É possível utilizar interfaces para contratos e objetos enquanto tipos são usados para unions, estados, aliases e outras composições.
Qual devo aprender primeiro?
Vale a pena aprender ambos. Comece entendendo como os dois definem objetos e, em seguida, estude os recursos específicos de cada um, como extends, Declaration Merging, Union Types e Intersection Types.
Conclusão
Entender a diferença entre interface e type no TypeScript permite tomar decisões melhores ao estruturar aplicações React, Node.js e projetos JavaScript modernos. Interfaces oferecem uma sintaxe clara para contratos, objetos e estruturas extensíveis, além de suportarem Declaration Merging. Já type se destaca pela flexibilidade na criação de unions, intersections, tuplas, aliases e combinações mais avançadas. Em vez de tratar a discussão como uma competição, o ideal é compreender o propósito de cada recurso. Como regra prática, pense em interface para objetos e contratos e em type para composição e tipos mais complexos. Ainda assim, priorize sempre consistência, clareza e os padrões estabelecidos pela sua equipe. Dessa forma, seu código TypeScript ficará mais previsível, organizado e fácil de manter.