Fala @guilzms, tudo tranquilo?
Minha visão sobre Type e Interface
A respeito de qual "modelagem" utilizar em relação ao projeto, no curso que estou fazendo de typescript tive a seguinte visão sobre o uso do alias type e interface:
TYPE: Geralmente utilizado para criar um atalho (alias) para um tipo customizado. Utilizado em tipos primitivos (string, boolean, number...):
type Categorias = 'design' | 'codigo' | 'descod';
function pintarCategoria(categoria: Categorias) {
if (categoria === 'design') {
console.log('Pintar vermelho');
} else if (categoria === 'codigo') {
console.log('Pintar verde');
} else if (categoria === 'descod') {
console.log('Pintar roxo');
}
}
INTERFACE: Geralmente são utilizadas para definirmos objetos, entretanto não possibilita renomear tipos primitivos.
interface InterfaceProduto {
nome: string;
preco: number;
teclado: number;
}
function preencherDados(dados: InterfaceProduto) {
document.body.innerHTML += `
<div>
<h2>${dados.nome}</h2>
<p>R$ ${dados.preco}</p>
<p>Inclui teclado: ${dados.teclado ? 'sim' : 'não'}</p>
</div>
`;
}
Um bom ponto de observação, é que quando você cria um alias type,você está criando um apelido e nada mais. O Type
é do tipo fechado, onde não é possível criar diferentes "versões" do mesmo tipo, então sua repetição gerará um Erro de TS:
// TYPE
type Window = {
title: string
}
type Window = {
ts: TypeScriptAPI
}
// Error: Duplicate identifier 'Window'.
Para realizar a adição de uma nova propriedade a um Type
, seria necessário fazer o seguinte processo:
type TipoCarro = {
rodas: number;
portas: number;
};
type TipoCarroComPreco = TipoCarro & {
preco: number;
};
const dado1: TipoCarroComPreco = {
preco: 20000,
rodas: 4,
portas: 5,
};
Já a Interface
é do tipo aberta, então a mesma possibilita adicionar ou alterar campos, e também extende-la apenas redeclarando a mesma :
// Redeclaração de campos
interface InterfaceCarro {
rodas: number;
portas: number;
}
interface InterfaceCarro {
preco: number;
}
const dado2: InterfaceCarro = {
preco: 20000,
rodas: 4,
portas: 5,
};
Conclusão
O Matheus Benites - PapoDe.Dev dá um excelente panorama sobre a utilização de types e Interface:
se precisamos declarar os tipos de uma classe e seus metodos utilizamos interface; se precisamos declarar os tipo das props de uma função usamos alias type; se precisar criar uma definição de tipo que será extendida por algo, nós usamos interface; se estamos criando um generic type para alguma funcionalidade, usamos interface.
Espero ter ajudado, até mais!
Fontes:
Matheus Benites - PapoDe.Dev Documentação - Curso de Typescript - Origamid
Muito boa essa definição! Gostei!
Após a leitura do material e das suas conclusões vejo que está parecido com a metodologia que estou aplicando atualmente onde:
- Parametros de métodos e funções: Type
- Classe, métodos e callbacks: Interface
- métodos e callbacks privados não repetidos em outras classes: Type
E quando digo sobre métodos repetidos me refiro a isto por exemplo:
interface modeloInterface {
dado: string;
}
class FornecedorUm {
consumirApi(): modeloInterface {
return {
dado: 'oi'
}
}
}
class FornecedorDois {
consumirApi(): modeloInterface {
return {
dado: 'tchau'
}
}
}
Nestes exemplos o retorno dado no método consumirApi
precisa ser identico em todas as classes.
E o legal que vi em vários materiais, seu comentário e também o que estava pensando sobre os type é que eles são somente um alias enquanto que a interface, assim como em outras linguagens, é um contrato que deve ter seus parâmetros e métodos aplicados dentro da classe ou método onde ela é aplicada obrigatóriamente enquanto que o type não.
Além do exemplo que citei no post original eu poderia implementar esse nível de interfaces também diretamente na classe.
interface EmpresaCallback {
doc: string
razao: string
}
type BrasilAPITypes = {
cnpj: string;
razao_social: string;
};
interface GlobalInterface {
formataPesquisaCnpj: (param: BrasilAPITypes) => EmpresaCallback
}
class ConsultaBrasilAPI implements GlobalInterface {
formataPesquisaCnpj(callbackApi: BrasilAPITypes): EmpresaCallback {
return {
doc: callbackApi.cnpj,
razao: callbackApi.razao_social
}
}
}
Mas essa modelagem no meu caso eu preferi não seguir porque a classe em si é modelo "único" e não vai se repetir enquanto que o meu método formataPesquisaCnpj
poderá se repetir em outra classe que receberá dados de outra fonte e o callback delas devem ser identicos indiferente da fonte de dados. Além que quero evitar o "interfaces hell" em toda a aplicação assim como existia com o callback hell antes do async/await hahaha :-D
Pelo que estou vendo de acordo com os comentários, alguns materiais, troca de experiências e o pouco que tenho de conhecimento é que não existe muito bem denifino do Typescript um "manual de boas práticas" sobre uso de interfaces diferentemente de outras linguagens.