Objetos

Objetos

Jornada Javascript: Dados não Primitivos

O conteúdo dessa lição se baseia na base dos dados não primitivos que aprendemos na 7° lição da jornada Javascript. Link abaixo!

Para acessar o link da lição, clique aqui.

Olá leitor, nesta lição nós iremos nos aprofundar um pouco mais sobre o uso de objetos no Typescript 

Apesar de nós já termos vistos alguns conceitos sobre eles anteriormente nesta jornada, aqui nós iremos focar exclusivamente no entendimento sobre objetos no Typescript (assim como fizemos com a lição de funções).

Vamos nessa? 😋

Recapitulando Objetos

No Javascript, podemos dizer que um objeto (também chamado de object literals) é um tipo de dado não primitivo que tem por objetivo armazenar um grupo de outros tipos de dados dentro de uma estrutura de chave e valor:

{
nome: 'Micilini Roll',
rank: 99,
status: true
}

O que nos permite armazenar um grupo de dados dentro de uma mesma variável, e que podem ter suas propriedades acessadas por meio de chave (key) e valor (value).

Mas como será que os objetos são representados no Typescript? É o que iremos descobrir agora!

Declarando Objetos com Typescript

Criar objetos com Typescript é bastante semelhante ao que estamos acostumados a fazer com Javascript.

const pessoa = {
 nome: 'Lucas',
 idade: 32,
 email: 'lucas@example.com'
};

"Não precisamos definir os tipos de dados daquele objeto antes de setá-los?".

Neste caso em específico, como estamos definindo um objeto de forma crua dentro de uma variável (sem usar interfaces ou tipos explícitos, já chegaremos nesta parte). O TypeScript irá inferir de forma automática (por de baixo dos panos) o tipo do objeto com base na sua estrutura. E por conta disso, não há a necessidade de se declarar seu tipo de forma explícita.

Mas... se mesmo assim você quiser deixar explícito os tipos de dados daquele objeto, você pode fazer uma tipagem adicional da seguinte forma:

const aluno: { nome: string; idade: number; matriculado: boolean } = {
 nome: 'Júlia',
 idade: 20,
 matriculado: true
};

Declarando Objetos com Propriedades Opcionais

Se você deseja que o seu objeto tenha propriedades opcionais, basta que você declare a última propriedade de modo que ela recebe um array da seguinte forma:

const cliente: { nome: string; telefone: string; [key: string]: any } = {
 nome: 'Fernanda',
 telefone: '1234-5678'
};

cliente.email = 'hey@micilini.com';
console.log(cliente.email); //Saída: hey@micilini.com

Declarando Objetos com Interfaces

Anteriormente na jornada Typescript, você aprendeu sobre o uso das Interfaces, que nada mais são do que "objetos" que são usados para definir uma especie de "contrato" que será usado dentro de uma função ou classe.

Usar interfaces é uma ótima alternativa para simplificar os parâmetros de um objeto que pertence a uma função ou classe, o que garante que tudo fique dentro dos conformes, e o desenvolvedor saiba quais tipos de dados aquela função ou classe recebe (vulgo padronizão).

Dessa forma, em vez de precisarmos passar um objeto longo para inúmeras funções:

function minhaFuncao({nome: string, idade: number, status: boolean}): void{
 //....
}

function minhaFuncaoDois({nome: string, idade: number, status: boolean}): void{
 //....
}

function minhaFuncaoTres({nome: string, idade: number, status: boolean}): void{
 //....
}

Nós passamos apenas uma Interface:

function minhaFuncao(data: Pessoa): void{
 //....
}

function minhaFuncaoDois(data: Pessoa): void{
 //....
}

function minhaFuncaoTres(data: Pessoa): void{
 //....
}

O que facilita bastante a manutenção do nosso código, pois a partir de agora, se por acaso precisássemos adicionar ou remover uma propriedade, fariámos isso modificando apenas a Interface (Pessoa) em vez de ter que fazer isso manualmente em todas as funções (minhaFuncao, minhaFuncaoDois, minhaFuncaoTres...).

Para definir um objeto a partir de uma interface é bem simples:

interface Pessoa {
 nome: string;
 idade: number;
 email?: string; // Propriedade opcional
}

const pessoaObj: Pessoa = {
 nome: 'João',
 idade: 30
 // email é opcional e pode ser omitido
};

No código acima, nós definimos uma interface chamada Pessoa que contém 3 propriedades: nome, idade e email (sendo este opcional).

Em seguida, definimos uma constante que representa um objeto puro em Javascript, mas que herda o "contrato" da interface (Pessoa).

Isso faz com que aquele objeto específico (pessoaObj) trabalhe somente com as propriedades que foram definidas dentro da interface (Pessoa).

Legal, agora vamos aplicar o mesmo conceito de objetos só que dentro de uma função:

interface Pessoa {
 nome: string;
 idade: number;
 email?: string; // Propriedade opcional
}

function mostraDadosPessoa(pessoa: Pessoa){
 console.log('Olá: ' + pessoa.nome);
 console.log('Sua Idade é: ' + pessoa.idade);
 if(pessoa.email != undefined){
 console.log('Parece que você enviou um e-mail também... legal, ele é: ' + pessoa.email);
 }
}

// Exemplo de uso da função com um objeto que corresponde à interface Pessoa
const pessoaExemplo: Pessoa = {
 nome: 'Fernanda',
 idade: 28,
 email: 'fernanda@example.com' // Este campo é opcional, então também pode ser omitido
};

mostraDadosPessoa(pessoaExemplo);

No código acima, nós temos a função mostraDadosPessoa que foi configurada para receber qualquer tipo de dado que está relacionado a interface Pessoa.

Que poderia ser uma função, um array, uma classe... mas no nosso caso foi um objeto simples mesmo 😋

Declarando Objetos com o Type

Assim como vimos no tópico anterior, também podemos declarar objetos usando o Type da seguinte forma:

type PessoaTipo = {
 nome: string;
 idade: number;
 email?: string;
}
 
const pessoaObjDois: PessoaTipo = {
 nome: 'Maria',
 idade: 25
};

Agora veja como nós podemos chegar no mesmo resultado usando funções:

type PessoaTipoDois = {
 nome: string;
 idade: number;
 email?: string;
};
 
function exibirPessoa(pessoa: PessoaTipoDois): void {
 console.log(`Nome: ${pessoa.nome}`);
 console.log(`Idade: ${pessoa.idade}`);
 
 // Verifica se o email está presente e o exibe
 if (pessoa.email) {
 console.log(`Email: ${pessoa.email}`);
 } else {
 console.log('Email não fornecido');
 }
}
 
// Criando um objeto pessoa
const pessoaObjTres: PessoaTipoDois = {
 nome: 'Maria',
 idade: 25
};
 
// Chamando a função para exibir as informações da pessoa
exibirPessoa(pessoaObj);

Assim como vimos em Interfaces, na função acima (exibirPessoa) nós estamos recebendo um parâmetro do tipo PessoaTipoDois que está intimamente ligado ao nosso Type.

Declarando Objetos que possuem funções dentro das Interfaces

Você também pode adicionar métodos aos seus objetos dentro das interfaces da seguinte forma:

interface Pessoa {
 nome: string;
 idade: number;
 falar(): void; // Método sem parâmetros e sem retorno
}

const pessoaObj: Pessoa = {
 nome: 'Carlos',
 idade: 40,
 falar: () => {
 console.log('Olá!');
 }
};

pessoa.falar(); // Saída: Olá!

No caso da interface (Pessoa), eu só precisei declarar o nome da função (aqui chamamos eles de métodos) e o tipo de retorno que aquela função teria (que no caso é sem retorno, ou seja, void).

Já dentro do objeto (pessoaObj) é o lugar onde declaramos o corpo da função em sí.

Declarando Objetos que possuem funções dentro de um Type

Vejamos agora como você pode adicionar métodos aos seus objetos dentro de um type:

interface PessoaDois {
 nome: string;
 idade: number;
 falar(): void; // Método sem parâmetros e sem retorno
}
 
const pessoaObjQuatro: PessoaDois = {
 nome: 'Carlos',
 idade: 40,
 falar: () => {
 console.log('Olá!');
 }
};
 
pessoaObjQuatro.falar(); // Saída: Olá!

Note que o funcionamento é praticamente o mesmo de uma interface, a única diferença é que as interfaces podem ter seus valores alterados enquanto os types não, ainda se lembra dessa regra?

Arquivos da lição

Os arquivos desta lição podem ser encontrados no repositório do GitHub por meio deste link.

Conclusão

Nesta lição você aprendeu sobre o uso dos objetos em Typescript, e ainda aprendeu o seu uso em conjunto com as Interfaces e Types.

Na próxima lição veremos o funcionamento dos arrays com Typescript 😀