Tipos e Dados
O conteúdo dessa lição se baseia na base dos tipos e dados que aprendemos na 3° lição da jornada Javascript. Link abaixo!
Para acessar o link da lição, clique aqui.
Assim como no Javascript, no Typescript nós também possuímos os mesmos tipos de dados, a diferença é que aqui eles são declarados de forma um pouco mais explicita.
Explicita no sentido de dizermos ao programa que tipo de dado aquela variável ou função vai trabalhar. E depois de definido o seu tipo, aquela variável ou função não poderá receber dados de outros tipos (ao menos que o tipo esteja declarado como any
).
Type Annotation e Type Inference
No universo do Typescript, nós podemos declarar nossos tipos de dados de duas formas diferentes:
- Type Annotation,
- Type Inference.
Type Annotation
Também conhecido como tipo de anotação, é quando definimos nossos tipos de dados de forma EXPLICITA!
E isso é feito adicionando o : tipo
após a declaração do nome de uma variável ou parâmetro de uma função:
let nomeDaVariavel: tipo = ...
Durante a nossa jornada iremos utilizar este tipo de anotação.
Type Inference
Também conhecido como tipo de inferência, é um recurso do próprio Typescript em que ele deduz de forma automática o tipo de uma variável ou expressão com base no valor inicial que foi atribuído a ela.
Ou seja, aqui o tipo de dado é declarado de forma IMPLÍCITA!
Que nada mais é do que fazer aquilo que já estamos acostumados com o Javascript, por exemplo:
let nome = "Micilini"//Deduz que é uma string
let idade = 28;//Deduz que é um number
Quando usar Type Annotation ou Type Inference?
Type Annotation: É útil quando você deseja especificar explicitamente o tipo de uma variável ou função, o que pode ajudar na clareza do código e na detecção de erros de tipo durante o desenvolvimento.
Type Inference: É conveniente e reduz a quantidade de código redundante, pois o TypeScript deduz automaticamente os tipos com base nos valores atribuídos. Isso pode tornar o código mais limpo e menos propenso a erros de digitação.
Sendo assim:
Use anotações de tipo quando quiser garantir explicitamente o tipo de uma variável ou função, especialmente em casos onde o tipo não é óbvio.
Tal prática que vamos adotar nesta jornada 😉
Tipos Primitivos em Typescript
No Typescript nós temos ao todo 7 diferentes tipos de dados primitivos, são eles:
Number
String
Boolean
Null
Undefined
BigInt
Symbol
Veremos o funcionamento de cada um deles abaixo 😉
Number
No typescript nós temos o tipo number
, que representa um valor numérico, que podem incluir tanto inteiros quanto números de ponto flutuante (decimais), podendo ser positivos ou negativos.
Veremos abaixo algumas caraterísticas do tipo number 🙂
Inteiros: o JavaScript moderno trata números como números de ponto flutuante de 64 bits, então o intervalo de inteiros é de aproximadamente de -9 quadrilhões a 9 quadrilhões.
Ponto Flutuante: além de números inteiros, podemos usar números fracionários (decimais) com precisão limitada.
Vejamos alguns exemplos no uso do number
em Typescript:
let idade: number = 30;
var preco: number = 99.99;
const temperatura: number = -10.5;
let pi: number = 3.14159;
let maiorNumero: number = Infinity;
let naoEhNumero: number = NaN;
Observe que declaramos essas variáveis usando o let
, var
e const
, assim como estamos acostumados a fazer no Typescript.
Observação: O Typescript possibilita também a inserção de métodos númericos.
String
No typescript, nós temos também o tipo string
, que representa uma string (um texto), que pode incluir diversos caracteres como letras, números além de caracteres especiais.
Vejamos alguns exemplos no uso da string
em Typescript:
let nome: string = "Maria";
const mensagem: string = 'Olá, mundo!';
var cumprimento: string = "Olá, " + nome + "!";//Exemplo de concatenação
Veja que estamos usando o termo string
logo após declararmos o nome da nossa variável.
Assim como fazemos no Javascript, o Typescript também aceita interpolação:
let idade: number = 30;
let mensagemIdade: string = `Você tem ${idade} anos.`;
Observação: O Typescript possibilita também a inserção de métodos de texto.
Boolean
No typescript, nós temos também o tipo boolean
, que representa um valor booleano (true
ou false
). Vejamos alguns exemplos do seu uso:
let ativo: boolean = true;
let maiorIdade: boolean = false;
let temContaBancaria: boolean = true;
let temCartaoCredito: boolean = false;
let elegivelParaEmprestimo: boolean = temContaBancaria && !temCartaoCredito;
let possuiPermissao: boolean = true;
Nos códigos acima estamos declarando um tipo boolean
, junto com exemplos de operadores lógicos, que por sua vez, permanecem os mesmos do Javascript.
Null e Undefined
Em TypeScript, assim como em JavaScript, null
e undefined
são dois valores distintos que são usados para representar a ausência de valor ou valores que não foram definidos.
Para verificar se uma variável é undefined
, você pode compará-la diretamente com undefined
:
let nome: string = "";
if (nome === undefined) {
console.log("O nome não foi definido.");
}
let carro: string | null = null;
let endereco: string | null = null;
if (endereco === null) {
console.log("O endereço não está disponível.");
}
Lembrando que não é possível definir tipos de variáveis como null
ou undefined
, como por exemplo:
let nulo: null = null;//Vai dar erro!
const naoDefinido: undefined = undefined;//Também vai dar erro
O que podemos fazer é: Definir um tipo e atribuí-lo como null
ou undefined
(enquanto aquela variável ainda não recebe nenhum valor):
let nome: string = null; // Erro se "strictNullChecks" estiver ativado
let idade: number = undefined; // Erro se "strictNullChecks" estiver ativado
No caso dos dois comandos acima, o primeiro recebe uma string
e o segundo um number
, e apesar de ambos estarem com valores nulos, eles só podem conter uma string (nome
) ou um número (idade
).
O que é o strictNullChecks e como ativar/desativar?
No typescript, existe uma configuração na qual deixamos o compilador mais rigoroso com relação aos valores null
e undefined
.
Ele é uma parte das opções de configuração de "strict mode"
do TypeScript, que são destinadas a melhorar a segurança e robustez do código, especialmente em relação ao tratamento de tipos.
Quando ativado, você não pode atribuir null
ou undefined
a uma variável que foi tipada explicitamente para não aceitar esses valores.
Como estamos usando o terminal (prompt de comando) para compilar códigos TS em JS, você pode ativar essa checagem passando a flag --strictNullChecks
da seguinte forma:
tsc --strictNullChecks arquivo.ts
Para manter desativado é só não passar essa tag, ok?
Agora, se você estiver usando Typescript com ReactJS ou NodeJS, basta que você ative essa opção criando uma nova chave dentro do arquivo tsconfig.json
, que geralmente fica localizado na pasta raiz da sua aplicação:
{
"compilerOptions": {
"strictNullChecks": true
}
}
BigInt
No typescript, também temos o bigint
que é números inteiros gigantescos, como por exemplo: 1234567890123456789012345678901234567890n
.
Importante: inicialmente o Bigint
pode estar desativado, isto é, quando o compilador do Typescript está setado para versões menores que ES2020, o que ocasionaria o seguinte erro: "BigInt literals are not available when targeting lower than ES2020".
Para resolver este erro, crie uma nova chave dentro do arquivo tsconfig.json
da seguinte forma:
{
"compilerOptions": {
"lib": [
"es2020"
],
"module": "commonjs",
"target": "es2020",
}
Para resolver isso via terminal, basta passar uma flag chamada de --target
da seguinte forma:
tsc --target ES2020 arquivo.ts
Agora vejamos como declarar este tipo de dado:
let numeroGrande: bigint = 1234567890123456789012345678901234567890n;
let a: bigint = 123n;
let b: bigint = 456n;
let soma: bigint = a + b; // 579n
let diferenca: bigint = b - a; // 333n
let produto: bigint = a * b; // 56088n
let quociente: bigint = b / a; // 3n (divisão de inteiros)
let resto: bigint = b % a; // 87n
No comando acima, vimos que também é possível realizar operações matemáticas com Typescript, e que elas não se diferem daquilo que vimos no JS.
Observação: O Typescript possibilita também a inserção de métodos de númericos para este tipo em específico.
let numero: number = 123;
let numeroGrande: bigint = BigInt(numero); // converte number para bigint
let numeroNovo: number = Number(numeroGrande); // converte bigint para number
Symbol
Por fim, nós temos o tipo symbol
é usado para criar valores únicos e imutáveis que são frequentemente usados como identificadores únicos em propriedades de objetos.
Vejamos como ele funciona:
let sym1 = Symbol();
let sym2 = Symbol("descricao");
Para usá-lo dentro de um objeto, basta fazer isso da seguinte forma:
const chave1 = Symbol("chave1");
const chave2 = Symbol("chave2");
let objeto = {
[chave1]: "valor1",
[chave2]: "valor2"
};
console.log(objeto[chave1]); // "valor1"
Fatos interessantes sobre o Typescript
Como você já sabe, o typescript precisa ser transformado para Javascript para ser executado tanto no front-end quanto no back-end.
Se você pegar todos os arquivos que criamos nesta lição, verá que na versão .js
de cada um deles, a tipagem estática que definomos em nossas variáveis, simplesmente some 😅
Esse é um comportamento normal, pois o JS não tem esse suporte de tipagem.
Dessa forma, conseguimos compreender que o Typescript é só uma ferramenta de apoio a criação de códigos mais "certos". Pois no final tudo será convertido para o nosso bom e velho Javascript.
Podemos dizer então que programar em TS é como um pair programming, mas o que é isso?
Pair programming é uma prática de desenvolvimento de software onde dois programadores trabalham juntos em um mesmo computador. Nesta abordagem, um dos programadores, chamado de "driver" (motorista), está encarregado de escrever o código, enquanto o outro, chamado de "navigator" (navegador), revisa cada linha de código à medida que é escrita.
No caso, o motorista somos nós, e o navegador é o compilador do TS 😊
Lembrando que após a compilação de código Typescript em Javascript, o Typescript não tem mais nenhum efeito, logo, ele não pode mais nos ajudar no desenvolvimento.
Gerando erros de tipagem estática com Typescript
Como vimos acima, nós aprendemos a declarar nossos tipos primitivos usando Typescript.
E para confirmar que o compilador gera erros quando tentamos atribuir outros tipos, nós vamos fazer o seguinte teste:
let nome: string = "Micilini Roll";
nome = 15.98;//Essa linha vai gerar um erro
console.log(nome);
Quando executamos um tsc index.ts
, o compilador vai gerar este erro:
Apesar de um arquivo index.js
ser gerado, vemos que o TS apontou um erro no momento em que tentamos atribuir um tipo number
para um tipo string
.
Em aplicações reais feitas com ReactJS ou NodeJS, um código como esse nunca seria compilado, ocasionando um erro na aplicação inteira.
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 declarar os tipos primitivos no Typescript.
Até a próxima 🙃