Tipos especiais com Typescript
Você sabia que podemos fazer o uso de alguns tipos especiais, como:
Enum
Types
Dentro de nossas aplicações feitas com React? Quer saber como isso é feito?
Então fique até o final desta lição e descubra 😉
Usando Enums
Como você já sabe, um Enum
nada mais é do que um meio que nós temos de formatar nossos objetos, por meio chaves e valores.
No ReactTS, você pode passar uma determinada chave para um componente usando uma prop
, para que futuramente você possa imprimir (ou processar) o valor dela dentro do componente.
No caso dos Enum
, como recomendação, eu sugiro que você crie eles dentro de uma pasta chamada enums, mais especificamente dentro da pasta src do seu projeto:
Isso vai ao encontro às boas práticas de organização por funcionalidade, que a propósito, você já aprendeu na jornada ReactJS 😋
Feito isso, vamos ver um exemplo bem simples da utilização de um Enum
.
Dentro da pasta enums (que você acabou de criar), vamos criar um novo arquivo chamado de StatusEnum.ts
, que será um arquivo responsável por definir um enum
, para os diferentes estados que um componente pode assumir.
enums > StateEnum.ts
:
export enum Status {
Success = 'Success',
Warning = 'Warning',
Error = 'Error',
}
Em seguida, vamos criar o nosso componente chamado de StatusBadge
, que representa um componente simples que faz o uso do nosso Enum
para mostrar uma mensagem personalizada.
components > StatusBadge.tsx
:
import React from 'react';
import { Status } from '../enums/StateEnum';
// Define o tipo para as props do componente
interface StatusBadgeProps {
status: Status;
}
// Define as cores para cada status
const statusColors: Record<Status, string> = {
[Status.Success]: 'green',
[Status.Warning]: 'yellow',
[Status.Error]: 'red',
};
// Componente StatusBadge
const StatusBadge: React.FC<StatusBadgeProps> = ({ status }) => {
return (
<span
style={{
padding: '0.5em 1em',
borderRadius: '4px',
backgroundColor: statusColors[status],
color: 'white',
fontWeight: 'bold',
}}
>
{status}
</span>
);
};
export default StatusBadge;
Para utilizar esse componente, basta que você passe via props
seus Enums
da seguinte forma:
import StatusBadge from './components/StatusBadge';
import { Status } from './enums/StatusEnum';
....
<StatusBadge status={Status.Success} />
<StatusBadge status={Status.Warning} />
<StatusBadge status={Status.Error} />
Vejamos agora, uma explicação um pouco mais detalhada de tudo o que aconteceu nos códigos anteriores.
Enum
: Definimos um enum
Status para os diferentes estados possíveis (Success, Warning, Error).
StatusBadge Component: O componente StatusBadge
recebe uma prop status do tipo Status
. Ele usa essa prop para definir a cor de fundo do badge com base no enum.
statusColors
: Um objeto statusColors
é usado para mapear cada status para uma cor específica.
Utilização: No componente escolhida, você pode utilizar o componente StatusBadge
passando diferentes valores do enum
para demonstrar diferentes estados.
Com a utilização de Enums
no ReactTS, você pode ter um código mais legível e menos propenso a erros.
Criando um Enum de Nomes
Para fixar ainda mais o conceito de Enums
, vamos criar um novo Enum
chamado de NomesEnum
.
enums > NomesEnum.ts
:
export enum NomesEnum {
Alice = 'Alice Journeys Linch',
Bob = 'Bob Cinclair',
Charlie = 'Charlie Downtown Niltur',
}
O código acima representa um enumerado, onde armazenamos os nomes de três pessoas diferentes.
A ideia é que o nosso componente possa receber a chave Alice
, Bob
ou Charlie
, e com isso, consiga ter acesso ao nome completo da pessoa.
Agora, chegou a hora de criar o nosso componente que vai fazer o uso desse Enum
:
components > MostraNome.tsx
:
import React from 'react';
import { NomesEnum } from '../enums/NomesEnum';
const MostraNome: React.FC<{ nome: NomesEnum }> = ({ nome }) => {
return <h1>{nome}</h1>;
};
export default MostraNome;
Note que recebemos o enumerado que acabamos de criar (NomesEnum
), e por meio da chave, estamos mostrando o valor armazenado dentro daquele enumerado.
Para usar o componente MostraNome
é bem simples, observe:
import MostraNome from './MostraNome';
import { NomesEnum } from './NomesEnum';
....
<MostraNome nome={NomesEnum.Alice} />
<MostraNome nome={NomesEnum.Bob} />
<MostraNome nome={NomesEnum.Charlie} />
Ficou mais claro que o uso dos Enums
faz com que os dados trafegados dentro dos nossos componentes, se tornem cada vez mais legíveis e esperados?
Essa é a grande sacada dessa funcionalidade, pois dessa forma, conseguimos padronizar a nível de objeto, os dados que estamos recebendo.
Apesar do código acima funcionar tranquilamente, a utilização de Enums
costuma ser bastante utilizada em conjunto com as interfaces
.
Observe um outro exemplo do mesmo componente MostraNome
, só que dessa vez trabalhando com Enums
+ Interfaces
:
components > MostraNome.tsx
:
import React from 'react';
import { NomesEnum } from './NomesEnum';
// Define o tipo para as props do componente
interface MostraNomeProps {
nome: NomesEnum;
}
const MostraNome: React.FC<NomeDisplayProps> = ({ nome }) => {
return <h1>{nome}</h1>;
};
export default MostraNome;
Enums sem Interface: No exemplo sem a interface, o tipo das props
é definido diretamente no componente como um tipo inline ({ nome: NomesEnum }
). Isso funciona muito bem para os casos mais simples, mas pode ser menos claro e menos flexível do que usar uma interface, especialmente à medida que o componente se torna mais complexo.
Enums com Interface: Usar uma interface (MostraNomeProps
) é útil para definir claramente a estrutura das props
, facilitando a leitura e a manutenção do código, além de proporcionar melhores mensagens de erro, e também autocompletar as ferramentas de desenvolvimento.
Para componentes simples, você pode optar por definir o tipo inline (enums sem interface), mas para projetos maiores ou componentes mais complexos, é recomendado usar enums
em conjunto com interfaces
para definir suas props
.
Usando Types
No momento, nós aprendemos a criar estruturas de tipo usando Interfaces
, mas você sabia que nós também podemos usufruir das Types?
Será por meio das Types
que nós conseguiremos criar dados com uma tipagem mais fixada, ou seja, tipos de dados fixos. Vamos ver na prática como podemos aplicar esse conceito no React
Para começarmos, vamos criar um componente que vai possuir um Type
que aceita somente dois tipos de valores: string
ou null
.
components > ExemploTypes.tsx
:
type textoOuNulo = string | null;
const ExemploTypes = () => {
const nome:textoOuNulo = null;
const sobrenome:textoOuNulo = "Roll";
const numero:textoOuNulo = 2; //O TS vai gerar uma mensagem de erro, pois só pode ser string ou null, e não um number
return nome + sobrenome;
}
export default ExemploTypes;
No caso do exemplo acima, criamos um Type
chamado de textoOuNulo
, que é um tipo que pode receber apenas dois valores: string
ou null
.
Note que a partir do momento em que tentamos atribuir qualquer outro tipo de valor que não seja uma string
ou um null
, o Typescript gera um erro no console:
const numero:textoOuNulo = 2; //O TS vai gerar uma mensagem de erro, pois só pode ser string ou null, e não um number
Vejamos um outro exemplo em que criamos valores pré-fixados:
components > ExemploTypes.tsx
:
type textoOuNulo = string | null;
type fixado = "Sucesso" | "Alerta" | "Perigo";
const ExemploTypes = () => {
const nome:textoOuNulo = null;
const sobrenome:textoOuNulo = "Roll";
const numero:textoOuNulo = 2; //O TS vai gerar uma mensagem de erro, pois só pode ser string ou null, e não um number
const mensagemUm:fixado = "Sucesso";
const mensagemDois:fixado = "Perigo";
const mensagemTres:fixado = "Micilini Roll";//O TS vai gerar uma mensagem de erro, pois os valores aceitos são apenas "Sucesso, Alerta e Perigo".
return nome + sobrenome;
}
export default ExemploTypes;
No código acima, nós criamos um tipo chamado de fixado, que só pode receber 3 tipos de dados do tipo string
: Sucesso
, Alerta
e Perigo
.
Qualquer outro tipo de dado, mesmo que ela seja uma string
, vai gerar um erro no Typescript:
const mensagemTres:fixado = "Micilini Roll";//O TS vai gerar uma mensagem de erro, pois os valores aceitos são apenas "Sucesso, Alerta e Perigo".
const mensagemQuatro: fixado = 11;//O TS vai gerar uma mensagem de erro, pois só aceita strings...
Agora, caso você queira fazer com que um determinado Type
, atue como se fosse uma Interface
, você pode fazer isso da seguinte forma:
components > Informacoes.tsx
:
import React from 'react';
// Definição do tipo para as props dentro do mesmo arquivo
type InformacoesProps = {
nome: string;
idade: number;
email: string;
};
const Informacoes: React.FC<InformacoesProps> = ({ nome, idade, email }) => {
return (
<div>
<h1>Informações</h1>
<p><strong>Nome:</strong> {nome}</p>
<p><strong>Idade:</strong> {idade}</p>
<p><strong>Email:</strong> {email}</p>
</div>
);
};
export default Informacoes;
Note que criamos um novo type
chamado de InformacoesProps
, que fica responsável por definir todas as propriedades que o nosso componente (Informacoes
) vai receber.
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 a usar os tipos especiais (Enum
e Type
) no ReactTS.
Até a próxima lição 😃