Revisão de TypeScript
---
id: 6724e296dceca21b82426229
title: Revisão de TypeScript
challengeType: 31
dashedName: review-typescript
---
# --description--
Arquivo
O que é TypeScript
- JavaScript: JavaScript é uma linguagem de tipagem dinâmica. Isso significa que variáveis podem receber quaisquer valores em tempo de execução. O desafio de uma linguagem de tipagem dinâmica é que a falta de segurança de tipo pode introduzir erros.
const getRandomValue = (array) => {
return array[Math.floor(Math.random() * array.length)];
}
console.log(getRandomValue(10));
A saída do console para o exemplo acima será undefined.
- TypeScript: TypeScript estende a linguagem JavaScript para incluir tipagem estática, o que ajuda a detectar erros causados por incompatibilidades de tipo antes de você executar seu código.
array da seguinte forma:
const getRandomValue = (array: string[]) => {
return array[Math.floor(Math.random() * array.length)];
}
Esta definição de tipo informa ao TypeScript que o parâmetro array deve ser um array de strings. Então, quando você chama getRandomValue e passa um número, você recebe um erro chamado erro de compilador.
- Compilador: Você primeiro precisa compilar o código TypeScript em JavaScript comum. Quando você executar o compilador, o TypeScript avaliará seu código e gerará um erro para quaisquer problemas onde os tipos não correspondem.
Tipos de Dados em TypeScript
- Tipos de Dados Primitivos em TypeScript: Para os tipos de dados primitivos
string,null,undefined,number,booleanebigint, o TypeScript oferece palavras-chave de tipo correspondentes.
let str: string = "Naomi";
let num: number = 42;
let bool: boolean = true;
let nope: null = null;
let nada: undefined = undefined;
- Array: Você pode definir um array de tipo específico com duas sintaxes diferentes.
const arrOne: string[] = ["Naomi"];
const arrTwo: Array<string> = ["Camperchan"];
- Objetos: Você pode definir a estrutura exata de um objeto.
const obj: { a: string, b: number } = { a: "Naomi", b: 42 };
Se você quer um objeto com quaisquer chaves, mas onde todos os valores devem ser strings, existem duas maneiras de defini-lo:
const objOne: Record<string, string> = {};
const objTwo: { [key: string]: string } = {};
- Outros Tipos Úteis no TypeScript:
any:anyindica que um valor pode ter qualquer tipo. Isso informa ao compilador para parar de se preocupar com o tipo dessa variável.unknown:unknowndiz ao TypeScript que você *se importa* com o tipo do valor, mas na verdade não sabe qual é.unknowné geralmente preferido em vez deany.void: Este é um tipo especial que você normalmente usará apenas ao definir funções. Funções que não têm um valor de retorno usam um tipo de retornovoid.never: Representa um tipo que nunca existirá.- Palavra-chave
type: Esta palavra-chave é comoconst, mas em vez de declarar uma variável, você pode declarar um tipo.
type stringOrNumber = string | number;
type bot = "camperchan" | "camperbot" | "naomi";
interface: Interfaces são como classes para tipos. Elas podem implementar ou estender outras interfaces, são especificamente tipos de objeto e geralmente são preferidas a menos que você precise de um recurso específico oferecido por uma declaraçãotype.
interface wowie {
zowie: boolean;
method: () => void;
}
- Definindo o Tipo de Retorno: Você também pode definir o *return type* da função.
const getRandomValue = (array: string[]): string => {
return array[Math.floor(Math.random() * array.length)];
}
Genéricos
- Definindo Tipo Genérico: Você pode definir um tipo genérico e referenciá-lo na sua função. Ele pode ser pensado como um parâmetro especial que você fornece para uma função para controlar o comportamento da definição de tipo da função.
const getRandomValue = <T>(array: T[]): T => {
return array[Math.floor(Math.random() * array.length)];
}
const val = getRandomValue([1, 2, 4])
A sintaxe <T> informa ao TypeScript que você está definindo um tipo genérico T para a função. T é um nome comum para tipos genéricos mas você pode usar qualquer nome.
Então, você informa ao TypeScript que o parâmetro array é um array de valores que correspondem ao tipo genérico, e que o valor retornado é um único elemento desse mesmo tipo.
- Especificando Argumento de Tipo na Chamada de Função: Você pode passar um argumento de tipo para uma chamada de função usando colchetes angulares entre o nome da função e seus parâmetros.
const email = document.querySelector<HTMLInputElement>("#email");
console.log(email.value);
Isso informa ao TypeScript que o elemento que você espera encontrar será um elemento input.
Refinamento de Tipo
- Refinamento por Veracidade: No exemplo abaixo, você recebe um erro do compilador ao tentar acessar a propriedade
valuedeemailporqueemail*pode* sernull.
const email = document.querySelector<HTMLInputElement>("#email");
console.log(email.value);
Você pode usar uma declaração condicional para confirmar que email é *truthy* antes de acessar a propriedade:
const email = document.querySelector<HTMLInputElement>("#email");
if (email) {
console.log(email.value);
}
Verificações de veracidade também podem funcionar na direção oposta:
const email = document.querySelector<HTMLInputElement>("#email");
if (!email) {
throw new ReferenceError("Could not find email element!")
}
console.log(email.value);
Lançar um erro termina a execução lógica deste código, o que significa que quando você chega à chamada console.log(), o TypeScript sabe que email *não pode* ser null.
- Encadeamento Opcional: O encadeamento opcional
?.também é uma forma de restrição de tipo, sob a mesma premissa de que o acesso à propriedade não pode acontecer se o valor deemailfornull.
const email = document.querySelector<HTMLInputElement>("#email");
console.log(email?.value);
- Operador
typeof: Você pode usar uma condicional para verificar o tipo da variável usando o operadortypeof.
const myVal = Math.random() > 0.5 ? 222 : "222";
if (typeof myVal === "number") {
console.log(myVal / 10);
}
- Palavra-chave
instanceof: Se o objeto vem de uma classe, você pode usar a palavra-chaveinstanceofpara restringir o tipo.
const email = document.querySelector("#email");
if (email instanceof HTMLInputElement) {
console.log(email.value);
}
- Casting: Quando o TypeScript não consegue determinar automaticamente o tipo de um valor, como o resultado do método
request.json()no exemplo abaixo, você receberá um erro do compilador. Uma forma de resolver isso é fazendo o casting do tipo, mas isso enfraquece a capacidade do TypeScript de detectar erros potenciais.
interface User {
name: string;
age: number;
}
const printAge = (user: User) =>
console.log(${user.name} is ${user.age} years old!)
const request = await fetch("url")
const myUser = await request.json() as User;
printAge(myUser);
- Type Guard: Em vez de fazer o cast do tipo, você pode escrever um type guard:
interface User {
name: string;
age: number;
}
const isValidUser = (user: unknown): user is User => {
return !!user &&
typeof user === "object" &&
"name" in user &&
"age" in user;
}
A sintaxe user is User indica que sua função retorna um valor booleano, que quando verdadeiro significa que o valor user satisfaz a interface User.
Arquivo tsconfig
tsconfig.json: As configurações do compilador do TypeScript ficam em um arquivotsconfig.jsonno diretório raiz do seu projeto.
{
"compilerOptions": {
"rootDir": "./src",
"outDir": "./prod",
"lib": ["ES2023"],
"target": "ES2023",
"module": "ES2022",
"moduleResolution": "Node",
"esModuleInterop": true,
"skipLibCheck": true,
"strict": true
},
"exclude": ["test/"]
}
Aqui estão as descrições das opções do compilador usadas no exemplo acima:
compilerOptions: A propriedadecompilerOptionsé onde você controla como o compilador TypeScript se comporta.rootDireoutDir: OrootDire ooutDirinformam ao TypeScript qual diretório contém seus arquivos fonte e qual diretório deve conter o código JavaScript transpilado.lib: A propriedadelibdetermina quais definições de tipo o compilador usa e permite que você inclua suporte para versões específicas do ES, o DOM e mais.moduleemoduleResolution: Omodulee omoduleResolutiontrabalham em conjunto para gerenciar como seu pacote usa módulos - seja CommonJS ou ECMAScript.esModuleInterop: OesModuleInteroppermite uma interoperabilidade mais suave entre CommonJS e módulos ES ao criar automaticamente objetos de namespace para importações.skipLibCheck: A opçãoskipLibCheckpula a validação dos arquivos.d.tsque não são referenciados por imports no seu código.strict: A flagstricthabilita várias verificações, como garantir o tratamento adequado de tipos anuláveis e avisar quando o TypeScript recorre aany.exclude: A propriedade de nível superiorexcludeindica ao compilador para ignorar esses arquivos TypeScript durante a compilação.