JavaScript é a linguagem de programação mais amplamente utilizada para desenvolvimento web. Mas ela carece de suporte para verificação de tipos, que é um recurso essencial das linguagens de programação modernas.
JavaScript foi originalmente projetada como uma linguagem de script simples. Sua natureza solta e a ausência de recursos cruciais de Programação Orientada a Objetos (POO) apresentam certos desafios para os desenvolvedores:
-
Documentação limitada e auto-completação.
-
Incapacidade de utilizar conceitos de POO.
-
Falta de segurança de tipos, levando a erros em tempo de execução.
-
Desafios em refatoração e manutenção.
-
Ausência de interfaces e pontos de integração.
TypeScript resolve esses problemas. Foi criado para tornar o JavaScript uma linguagem de programação moderna mais perfeita. Ajuda a melhorar a experiência do desenvolvedor, oferece muitos recursos úteis e melhora a interoperabilidade.
Este artigo aborda os fundamentos do TypeScript. Vou te ensinar como instalar o TS e configurar um projeto. Em seguida, cobriremos alguns fundamentos importantes. Você também aprenderá como o TypeScript é compilado em JavaScript, tornando-o compatível com navegadores e ambientes Node.js.
O que vamos cobrir:
Pré-requisitos
Antes de mergulhar no TypeScript, é importante ter uma compreensão básica de certos conceitos para garantir uma jornada de aprendizado mais tranquila. Enquanto o TypeScript aprimora o JavaScript com tipagem estática e outras funcionalidades poderosas, ele se baseia nos princípios fundamentais do JavaScript. Aqui está o que você deve saber:
1. Fundamentos do JavaScript
O TypeScript é um superconjunto do JavaScript, o que significa que ele estende as capacidades do JavaScript. Para aprender TypeScript de forma eficaz, você deve primeiro ter um entendimento sólido dos conceitos básicos do JavaScript, incluindo:
-
Sintaxe e tipos de dados: Entenda como declarar variáveis (
let
,const
, evar
), trabalhar com tipos primitivos (strings, números, booleanos) e gerenciar arrays e objetos. -
Fluxo de controle: Esteja familiarizado com loops (
for
,while
), condicionais (if-else
,switch
) e como eles controlam a execução do programa. -
Funções: Saiba como definir e invocar funções, trabalhar com parâmetros, retornar valores e entender conceitos como funções de seta e closures.
-
Programação Orientada a Objetos (POO): Aprenda sobre a criação e o trabalho com objetos, classes e herança. Os recursos baseados em classes do TypeScript são construídos fortemente no modelo de POO do JavaScript.
-
Tratamento de erros: Entenda como usar blocos
try-catch
para lidar com erros em tempo de execução.
2. HTML e CSS básicos
Embora o TypeScript seja uma linguagem usada principalmente com JavaScript, ter um entendimento básico de HTML e CSS é útil, especialmente para desenvolvedores front-end. Isso ocorre porque a maioria dos projetos TypeScript envolve a criação ou o trabalho com aplicações web
-
HTML: Entenda como estruturar páginas da web usando tags, atributos e elementos.
-
CSS: Aprenda como estilizar elementos usando seletores, propriedades e valores. Familiaridade com frameworks CSS como Bootstrap é um diferencial.
3. Familiaridade com Ferramentas de Desenvolvimento
-
Um editor de código como o Visual Studio Code, que tem excelente suporte ao TypeScript e extensões.
-
Node.js e npm: Entenda como configurar um ambiente de desenvolvimento, executar JavaScript fora do navegador e usar npm (Node Package Manager) para instalar dependências.
-
Controle de versão (Git): Aprenda o básico do Git para rastrear alterações e colaborar efetivamente em projetos TypeScript.
Começando – Como Instalar o TypeScript
Para começar a trabalhar com o TypeScript, você precisará instalá-lo. Não é um processo complicado. Com o TypeScript instalado, você pode aproveitar seu poder para criar soluções de alta qualidade.
Você pode instalar o TS de duas maneiras:
- Instalação Global: permite acessar o compilador de qualquer diretório em sua máquina. Para instalar o TypeScript globalmente, execute o seguinte comando:
npm install -g typescript
Este comando utiliza o gerenciador de pacotes Node.js, npm
. Ele instala o TypeScript globalmente, tornando o comando disponível na linha de comando.
- Instalação Local: neste caso, o TypeScript é instalado apenas em um projeto específico. Este método garante a compatibilidade de versão e consistência entre os membros da equipe. Para instalar o TypeScript localmente, execute o seguinte comando:
npm install typescript --save-dev
Diferente da instalação global, este comando instala o TypeScript como uma dependência de desenvolvimento. O comando tsc
está disponível apenas para uso específico do projeto, ou seja, no projeto específico onde você executa o comando.
Você consegue instalar o TypeScript facilmente agora? Espero que sim!
Como Organizar Seus Projetos TypeScript
Organizar um projeto TypeScript envolve estruturar seus arquivos com nomes e diretórios significativos, separando preocupações e usando módulos para encapsulamento e reutilização.
A extensão .ts
denota arquivos TypeScript e contém código que é convertido em JavaScript para execução.
TypeScript também suporta arquivos .d.ts
, também conhecidos como arquivos de definição de tipo. Esses arquivos oferecem informações de tipo sobre bibliotecas ou módulos JavaScript externos, auxiliando em uma melhor verificação de tipos e conclusão de código, além de melhorar a eficiência do desenvolvimento. Abaixo está um exemplo de uma boa estrutura de projeto TS:
my-ts-project/
├── src/
│ ├── components/
│ │ ├── Button.tsx
│ │ ├── Input.tsx
│ │ └── Modal.tsx
│ ├── services/
│ │ ├── api.ts
│ │ └── authService.ts
│ ├── utils/
│ │ ├── helpers.ts
│ │ └── validators.ts
│ ├── models/
│ │ ├── User.ts
│ │ └── Product.ts
│ ├── index.tsx
│ └── styles/
│ ├── global.css
│ └── theme.css
├── public/
│ ├── index.html
│ └── assets/
│ ├── images/
│ └── fonts/
├── tsconfig.json
└── package.json
Vamos entender o que está acontecendo aqui:
-
src/
: Este diretório abriga todo o código-fonte do projeto.-
components/
: Contém componentes de UI reutilizáveis (por exemplo,Button
,Input
,Modal
). Usar.tsx
(TypeScript JSX) permite que você escreva JSX com segurança de tipo. -
services/
: Abriga serviços que interagem com APIs externas ou lidam com a lógica da aplicação (por exemplo,api.ts
para chamadas de API,authService.ts
para autenticação). -
utils/
: Contém funções auxiliares e classes utilitárias para tarefas comuns (por exemplo,helpers.ts
para formatação de datas,validators.ts
para validação de entrada). -
models/
: Define interfaces ou classes TypeScript para representar estruturas de dados (por exemplo,User.ts
,Product.ts
). -
index.tsx
: O ponto de entrada principal da aplicação. -
styles/
: Contém arquivos CSS ou outros arquivos de estilo.
-
-
public/
: Este diretório contém ativos estáticos que não são processados pelo TypeScript (por exemplo, HTML, imagens, fontes). -
tsconfig.json
: O arquivo de configuração do TypeScript, especificando opções do compilador. -
package.json
: O arquivo manifesto do projeto, listando dependências, scripts e outros metadados do projeto.
Só uma rápida nota sobre convenções de nomenclatura para que você as entenda aqui:
-
Use PascalCase para nomes de classes (por exemplo,
User
,Product
). -
Use camelCase para nomes de funções e variáveis (por exemplo,
getUser
,firstName
). -
Use nomes significativos e descritivos para arquivos e diretórios.
Essa estrutura promove modularidade, reutilização e melhor organização, tornando seus projetos TypeScript mais fáceis de manter e escalar.
Organizar adequadamente seus projetos TypeScript melhora a manutenção do código, a legibilidade e a colaboração nos fluxos de trabalho de desenvolvimento em TypeScript.
Como as Tipagens Funcionam no TypeScript
Assim como qualquer outra linguagem de programação tipada, o TypeScript depende de definições de tipo, geralmente chamadas de Tipagem.
Tipagem é um termo utilizado na programação para definir os tipos de dados para variáveis, parâmetros de métodos e valores de retorno dentro do código.
A tipagem permite identificar erros rapidamente e cedo no desenvolvimento, um superpoder que ajuda a manter uma melhor qualidade de código.
Para especificar um tipo no TypeScript, coloque dois pontos (:
) e o tipo de dado desejado após o nome da sua variável. Aqui está um exemplo:
let age: number = 2;
A variável acima é declarada com o tipo number
. No TypeScript, isso significa que ela pode armazenar apenas números e mais nada.
Técnicas de Tipagem
No TypeScript, os dados podem ser tipados de duas maneiras principais:
- Tipagem Estática: A tipagem estática refere-se a especificar explicitamente o tipo de dados das variáveis e outras entidades no código durante o desenvolvimento. O compilador TypeScript faz cumprir essas definições de tipo, ajudando a identificar erros relacionados a tipos precocemente. Por exemplo:
let age: number = 25;
Aqui, a variável age
é explicitamente declarada como tendo o tipo number
. Isso garante que apenas valores numéricos possam ser atribuídos a ela, reduzindo o risco de erros em tempo de execução.
- Tipagem Dinâmica: A tipagem dinâmica em TypeScript refere-se a cenários onde o tipo de uma variável é determinado em tempo de execução. Isso pode ocorrer quando variáveis são atribuídas ao tipo
any
, que permite que elas contenham valores de qualquer tipo. TypeScript não realiza verificação de tipos em operações envolvendo variáveis com o tipoany
.
let value: any;
value = 25; // Número
value = "Hello"; // String
Ainda que TypeScript seja principalmente uma linguagem de tipagem estática, a tipagem dinâmica pode ser útil em casos específicos, como:
-
Trabalhar com bibliotecas de terceiros que não possuem definições de tipo.
-
Interagir com dados estruturados dinamicamente (por exemplo, respostas JSON de APIs com estruturas desconhecidas).
-
Prototipagem rápida ou quando informações de tipo estão indisponíveis durante a fase inicial de desenvolvimento.
Tipagem Estática vs. Tipagem Dinâmica em TypeScript
A tipagem estática é significativamente mais comum no TypeScript, pois é uma das características principais que diferencia o TypeScript do JavaScript. Ao impor verificações de tipo rigorosas, a tipagem estática aprimora a manutenção do código, reduz bugs e melhora a produtividade do desenvolvedor.
A tipagem dinâmica é tipicamente reservada para casos em que é necessária flexibilidade ou ao lidar com dados cuja estrutura não pode ser determinada antecipadamente. Apenas tenha em mente que depender fortemente da tipagem dinâmica (por exemplo, abusar do tipo any
) geralmente não é recomendado, pois mina os benefícios do sistema de tipagem estática do TypeScript.
Portanto, enquanto a tipagem dinâmica tem seu lugar em certos casos específicos, a tipagem estática é a abordagem preferida e mais comumente utilizada no desenvolvimento em TypeScript.
Inferência de Tipo e Tipos de União
Inferência de Tipo
A inferência de tipo é uma poderosa funcionalidade do TypeScript que permite ao compilador deduzir automaticamente o tipo de uma variável com base no valor atribuído a ela durante a inicialização. Em termos mais simples, o TypeScript analisa o valor atribuído a uma variável e decide qual deve ser o tipo, mesmo que você não declare explicitamente o tipo.
Por exemplo:
typescriptCopyEditlet age = 25; // O TypeScript infere que 'idade' é do tipo 'number'
age = "hello"; // Erro: O tipo 'string' não é atribuível ao tipo 'number'
Neste exemplo, a variável age
é automaticamente inferida como um número
por causa de seu valor inicial, 25
. Qualquer tentativa de reatribuir age
a um valor de um tipo diferente (como uma string) resultará em um erro de tipo.
A inferência de tipo é particularmente útil porque reduz a necessidade de anotações de tipo explícitas, tornando seu código mais limpo e legível. No entanto, ainda fornece a segurança e confiabilidade da verificação de tipo do TypeScript.
Quando usar inferência de tipo:
-
Atribuições simples: Use inferência de tipo para atribuições diretas onde o tipo é óbvio a partir do valor.
-
Valores padrão: Ao fornecer valores padrão para variáveis ou parâmetros de função, a inferência de tipo garante que o tipo correto seja aplicado sem a necessidade de anotações manuais.
-
Prototipagem rápida: Durante as fases iniciais de desenvolvimento, a inferência de tipo pode reduzir o código de boilerplate, ao mesmo tempo que mantém a segurança de tipo.
Tipos de União
Os tipos união permitem que uma variável contenha valores de múltiplos tipos. Eles são definidos colocando um pipe (|
) entre os tipos. Essa funcionalidade é particularmente útil quando uma variável pode legitimamente ter mais de um tipo durante seu ciclo de vida.
Por exemplo:
typescriptCopyEditlet numOrString: number | string; // 'numOrString' pode conter tanto um número quanto uma string
numOrString = 25; // Válido
numOrString = "hello"; // Válido
numOrString = true; // Erro: O tipo 'boolean' não é atribuível ao tipo 'number | string'
Você até pode definir tipos união com mais de dois tipos possíveis:
typescriptCopyEditlet multiType: number | string | boolean;
multiType = 42; // Válido
multiType = "TypeScript"; // Válido
multiType = false; // Válido
Quando usar tipos união:
-
Parâmetros de função flexíveis: Quando uma função pode aceitar múltiplos tipos de entrada.
typescriptCopyEditfunction printValue(value: string | number) { console.log(value); }
-
Manuseio de estruturas de dados diversas: Ao trabalhar com APIs ou fontes de dados externas onde os campos podem variar em tipo.
-
Variáveis opcionais ou de vários estados: Por exemplo, uma variável que pode representar um estado de carregamento como um booleano, um erro como uma string, ou dados válidos como um objeto:
typescriptCopyEditlet status: boolean | string | { success: boolean; data: any };
Como Lidar com Objetos, Arrays e Tipos de Função em TypeScript
Para dominar o TypeScript, é necessário entender os vários tipos de dados suportados no TypeScript e como e quando usá-los.
Os tipos primitivos do JavaScript como strings, números, booleanos e mais também definem os blocos de construção fundamentais de dados no TypeScript. Mas em particular, Objetos
, Arrays
, e Funções
são essenciais para construir aplicações robustas. Com objetos, arrays e funções, você pode lidar melhor com os dados e usá-los de forma eficiente no desenvolvimento.
Tipos de Objeto no TypeScript
Os tipos de objeto representam o modelo para criar objetos no TypeScript. Você pode usar objetos para definir sua estrutura, similar a como as classes são usadas na programação orientada a objetos (OOP). Mas os objetos carecem dos aspectos comportamentais e de encapsulamento que as classes oferecem.
Para definir um tipo de objeto, defina explicitamente o modelo do objeto após os dois pontos(:
). Por exemplo:
// Inicialização do Tipo de Objeto
let student: {
name: string;
age: number;
matricNumber: string | number;
};
// Atribuindo o Objeto com dados reais
student = {
name: "Akande"
age: 21,
matricNumber: 21/52 + "HP" + 19,
};
Observe que as propriedades terminam com um ponto e vírgula;
em vez de uma vírgula ,
que as encerraria em um objeto real.
O acima é a maneira principal de definir um objeto no TypeScript. Outra forma é usar interfaces
, as quais eu abordarei mais tarde neste artigo.
Tipos de Array no TypeScript
Arrays em TypeScript permitem que você armazene múltiplos valores do mesmo ou de diferentes tipos de dados em uma única variável. Eles aprimoram a segurança e clareza do seu código ao impor consistência de tipo em todos os elementos da matriz.
Em TypeScript, os tipos de array podem ser definidos de duas maneiras:
1. Usando o modelo Array<tipo>
Esta sintaxe utiliza o tipo genérico Array
, onde tipo
representa o tipo de elementos que a matriz pode conter.
typescriptCopyEditlet numbers: Array<number> = [1, 2, 3, 4, 5];
let mixedArray: Array<number | string> = [1, 2, 3, 4, 5, "Hello"];
-
Exemplo: Este array pode conter apenas números. Tentar adicionar uma string ou outro tipo a este array resultará em um erro de tipo.
typescriptCopyEditnumbers.push(6); // Válido numbers.push("Olá"); // Erro: O tipo 'string' não é atribuível ao tipo 'number'
-
mixedArray
Exemplo: Este array utiliza um tipo de união (number | string
), permitindo armazenar tanto números quanto strings.typescriptCopyEditmixedArray.push(42); // Válido mixedArray.push("TypeScript"); // Válido mixedArray.push(true); // Erro: O tipo 'boolean' não é atribuível ao tipo 'number | string'
2. Usando o type[]
modelo
Esta sintaxe acrescenta colchetes angulares ([]
) ao tipo de elementos que o array pode conter.
typescriptCopyEditconst numbers: number[] = [1, 2, 3, 4, 5];
const mixedArray: (string | number)[] = [1, 2, 3, 4, 5, "Hello"];
-
números
Exemplo: Similar ao exemploArray<number>
, este array pode conter apenas números.typescriptCopyEditnúmeros[0] = 10; // Válido números.push("Oi"); // Erro: O tipo 'string' não é atribuível ao tipo 'number'
-
mixedArray
Exemplo: Assim como omixedArray
anterior, este array permite tanto números quanto strings, proporcionando flexibilidade onde o tipo de dado pode variar.typescriptCopyEditmixedArray[1] = "Mundo"; // Válido mixedArray.push(true); // Erro: Tipo 'boolean' não pode ser atribuído ao tipo 'string | number'
Como Usar Arrays em TypeScript
Arrays são versáteis e comumente usados para armazenar coleções de dados relacionados. Aqui estão alguns cenários práticos:
Armazenando Dados Homogêneos:
Quando todos os elementos no array compartilham o mesmo tipo, como uma lista de IDs de usuários ou preços de produtos:
typescriptCopyEditconst userIds: number[] = [101, 102, 103];
const productPrices: Array<number> = [29.99, 49.99, 19.99];
Armazenando Dados Heterogêneos:
Quando os elementos podem ter tipos diferentes, como uma lista de mensagens contendo texto e metadados opcionais:
typescriptCopyEditconst messages: (string | object)[] = [
"Welcome",
{ type: "error", text: "Something went wrong" },
];
Iterando Sobre Arrays:
Arrays em TypeScript podem ser usados em loops com total segurança de tipos:
typescriptCopyEditconst scores: number[] = [80, 90, 70];
scores.forEach((score) => console.log(score + 5)); // Adiciona 5 a cada pontuação
Parâmetros de Função e Tipos de Retorno:
Arrays também podem ser passados como parâmetros de função ou retornados por funções com tipagem rigorosa:
typescriptCopyEditfunction getNumbers(): number[] {
return [1, 2, 3];
}
function printStrings(strings: string[]): void {
strings.forEach((str) => console.log(str));
}
Tipos de Função em TypeScript
Os tipos de função em TypeScript descrevem a forma das funções, incluindo tipos de parâmetros e tipos de retorno. Os tipos de função são definidos especificando explicitamente os tipos de parâmetros durante a declaração. O tipo de retorno é especificado adicionando :
e o tipo a ser retornado imediatamente após os parênteses. Por exemplo:
function addition (a: number, b: number): number {
return a + b;
}
A função acima recebe dois números, os adiciona e retorna um número. A função não funcionará se algum de seus argumentos não for um número e se retornar qualquer coisa além de um número. Por exemplo:
- Chamando a função com uma string como argumento:
// Isso não funcionará porque espera números, e um dos argumentos é uma string
addition(1, "two");
- Reescrevendo a função para retornar uma string:
// A função retornará um erro porque está retornando uma string
function addition (a: number, b: number): string {
let result = a + b;
let returnStatement = `Addition of ${a} and ${b} is: ${result}`;
return returnStatement;
}
Teste o código você mesmo para ver como esses exemplos funcionam.
Entender e lidar efetivamente com objetos, arrays e funções em TypeScript permite que você escreva código seguro em tipos e manutenível, melhorando a confiabilidade e escalabilidade de suas aplicações.
Como Criar Tipos Personalizados em TypeScript
Frequentemente, seu padrão de design não segue os tipos de dados embutidos em TypeScript. Por exemplo, você pode ter padrões que utilizam programação dinâmica. E isso pode causar problemas na sua base de código. TypeScript oferece uma solução para criar tipos personalizados para resolver esse problema.
Tipos personalizados permitem que você defina sua estrutura de dados e formas de acordo com suas necessidades. Isso melhora a legibilidade e a manutenibilidade do código.
A Palavra-chave Type
A palavra-chave type
permite que você crie aliases de tipo, proporcionando uma maneira de criar tipos personalizados. Os tipos que você cria podem ser reutilizados em toda a sua base de código. Aliases de tipo ajudam a definir tipos de união ou combinar tipos em aliases únicos. A sintaxe para criar um tipo personalizado é a seguinte:
// Sintaxe
type TypeAlias = type;
E aqui está um exemplo:
O código acima cria um tipo personalizado UserName
, uma união de números e strings. Ele usa o tipo criado para definir duas variáveis relativamente para verificar se o tipo funciona.
Note que é recomendado que um alias de tipo comece com uma letra maiúscula.
A palavra-chave type é geralmente usada para primitivos – mas que tal criar um tipo de objeto personalizado?
É aqui que entram as Interfaces.
Interfaces do TypeScript
Interfaces em TypeScript são usadas para definir a estrutura de objetos. Elas servem como modelos, especificando as propriedades que um objeto deve ter e seus respectivos tipos. Isso garante que os objetos sigam uma forma consistente, possibilitando segurança de tipo e um código mais claro.
Definindo uma interface
Uma interface é definida usando a palavra-chave interface
. A sintaxe se parece com isto:
typescriptCopyEditinterface InterfaceName {
property1: Type;
property2: Type;
}
Exemplo:
typescriptCopyEditinterface User {
id: number;
name: string;
email: string;
}
const user: User = {
id: 1,
name: "Alice",
email: "[email protected]",
};
Aqui está o que está acontecendo neste exemplo:
-
Declaração da interface (
interface User
):-
Aqui, definimos um modelo para um objeto
User
. Ele especifica que qualquer objeto do tipoUser
deve ter as seguintes propriedades:-
id
do tiponumber
-
name
do tipostring
-
email
do tipostring
-
-
-
Usando a interface (
const user: User
):-
Nós declaramos um objeto
user
do tipoUser
. -
O objeto precisa ter todas as propriedades definidas na interface
User
, com valores dos tipos especificados. Se uma propriedade estiver faltando ou seu tipo não corresponder, o TypeScript lançará um erro em tempo de compilação.
-
Por exemplo:
typescriptCopyEditconst invalidUser: User = {
id: 1,
name: "Alice",
// Erro: Propriedade 'email' está faltando no tipo
};
Então você pode estar se perguntando – por que você deve usar interfaces?
-
Segurança de tipo: Garante que os objetos se conformem à estrutura esperada, prevenindo erros em tempo de execução.
-
Reutilização: A mesma interface pode ser reutilizada em diferentes partes da aplicação, reduzindo duplicações.
-
Clareza de código: Torna o código mais fácil de ler e entender ao descrever explicitamente a forma dos objetos.
Recursos Avançados de Interfaces
-
Propriedades opcionais: Você pode tornar as propriedades opcionais adicionando um ponto de interrogação (
?
).typescriptCopiaEditarinterface Produto { id: number; nome: string; descrição?: string; // Propriedade opcional } const produto: Produto = { id: 101, nome: "Laptop", }; // Válido, pois 'descrição' é opcional
-
Propriedades somente leitura: Use
readonly
para evitar que as propriedades sejam modificadas após a inicialização.typescriptCopyEditinterface Point { readonly x: number; readonly y: number; } const point: Point = { x: 10, y: 20 }; point.x = 15; // Erro: Não é possível atribuir a 'x' porque é uma propriedade somente leitura
-
Estendendo interfaces: As interfaces podem herdar propriedades de outras interfaces, permitindo a composição.
typescriptCopyEditinterface Pessoa { nome: string; idade: number; } interface Funcionário extends Pessoa { idFuncionário: number; } const funcionário: Funcionário = { nome: "João", idade: 30, idFuncionário: 1234, };
Quando usar Interfaces
Há vários cenários em que é uma boa ideia usar interfaces. Você pode usá-las quando deseja definir e fazer cumprir a estrutura de objetos que circulam em seu código.
Também são úteis em respostas de API, pois ajudam a verificar o tipo de objetos recebidos das APIs. Isso garante que os dados estejam de acordo com suas expectativas.
As interfaces também são úteis ao trabalhar com tipos reutilizáveis. Quando várias partes de sua aplicação usam objetos com a mesma estrutura, as interfaces evitam a duplicação.
Ao aproveitar as interfaces, você pode criar aplicativos robustos, mantíveis e seguros em relação aos tipos. Elas são um recurso essencial do TypeScript que promove um código limpo e previsível.
Genéricos e Tipos Literais
Genéricos no TypeScript permitem que você crie componentes reutilizáveis que podem trabalhar com vários tipos de dados. Eles permitem que você escreva funções, classes e interfaces sem especificar o tipo exato antecipadamente, tornando seu código mais flexível e mantível.
Aqui está um exemplo de uma função genérica e uma interface genérica em TypeScript:
// Interface genérica para uma caixa que pode conter qualquer valor
interface Box<T> {
value: T;
}
// Exemplos de uso
let numberBox: Box<number> = { value: 10 };
let stringBox: Box<string> = { value: "TypeScript" };
console.log(numberBox.value); // Saída: 10
console.log(stringBox.value); // Saída: TypeScript
Você pode usar genéricos quando não tem certeza do tipo de dados.
Em contraste com Generics, Tipos literais permitem que você especifique valores exatos que uma variável pode conter. Isso adiciona maior especificidade e segurança de tipo ao seu código, prevenindo que valores indesejados sejam atribuídos. Aqui está um exemplo:
type Direction = 'up' | 'down' | 'left' | 'right';
Uma variável criada com o tipo acima só pode ser atribuída para as strings up, down, left e right.
No geral, aproveitar tipos personalizados em TypeScript capacita você a criar estruturas de dados expressivas, reutilizáveis e seguras em termos de tipo, ajudando você a desenvolver aplicações mais robustas e sustentáveis.
Como Mesclar Tipos em TypeScript
Mesclar tipos em TypeScript combina várias declarações de tipo em um único tipo unificado. Essa capacidade permite que os desenvolvedores construam tipos complexos a partir de peças menores e reutilizáveis, aumentando a clareza, reutilização e manutenção do código.
1. Mesclagem de Declaração em Interfaces
TypeScript suporta mesclagem de declaração, onde várias declarações de interface com o mesmo nome são automaticamente combinadas em uma única interface. Isso permite que você amplie uma interface existente definindo propriedades ou métodos adicionais.
Exemplo:
typescriptCopyEditinterface User {
id: number;
name: string;
}
interface User {
email: string;
}
const user: User = {
id: 1,
name: "Alice",
email: "[email protected]",
};
Como funciona:
-
A interface
User
é declarada duas vezes, cada uma com propriedades diferentes. -
O TypeScript mescla automaticamente essas declarações em uma única interface:
typescriptCopyEditinterface User { id: number; name: string; email: string; }
-
Ao criar o objeto
user
, todas as propriedades da interface mesclada devem estar presentes. Se alguma propriedade estiver faltando, o TypeScript emitirá um erro.
A mesclagem de declarações é particularmente útil ao trabalhar com bibliotecas de terceiros. Você pode estender ou adicionar novas propriedades a uma interface existente sem modificar o código-fonte da biblioteca.
2. Mesclagem de Interfaces Usando a Palavra-chave extends
A palavra-chave extends
permite que uma interface herde propriedades e métodos de outra, criando uma nova interface que combina as propriedades de ambas.
Exemplo:
typescriptCopyEditinterface Person {
name: string;
age: number;
}
interface Employee extends Person {
employeeId: number;
}
const employee: Employee = {
name: "John",
age: 30,
employeeId: 101,
};
Como funciona:
-
A interface
Person
define duas propriedades:name
eage
. -
A interface
Employee
usa a palavra-chaveextends
para herdar as propriedades daPerson
. -
A interface
Employee
também adiciona uma nova propriedade,employeeId
. -
O objeto
employee
deve incluir todas as propriedades tanto dePerson
quanto deEmployee
.
Essa abordagem é ideal para relações hierárquicas. Por exemplo, você pode definir uma interface base para propriedades compartilhadas e estendê-la para tipos especializados.
3. Mesclagem de Tipos Usando o &
Operador
O operador &
, conhecido como tipo de interseção, permite combinar múltiplos tipos em um único tipo. O tipo resultante inclui todas as propriedades e métodos de cada tipo.
Exemplo:
typescriptCopyEdittype Address = {
city: string;
country: string;
};
type ContactInfo = {
email: string;
phone: string;
};
type EmployeeDetails = Address & ContactInfo;
const employee: EmployeeDetails = {
city: "New York",
country: "USA",
email: "[email protected]",
phone: "123-456-7890",
};
Como funciona:
-
Address
eContactInfo
são dois tipos separados. -
Detalhes do Funcionário
é um tipo de interseção criado usandoEndereço & Informações de Contato
. -
O objeto
funcionário
deve incluir todas as propriedades tanto deEndereço
quanto deInformações de Contato
. Propriedades ausentes ou incorretamente digitadas resultarão em um erro do TypeScript.
Os tipos de interseção são úteis quando você precisa combinar tipos não relacionados ou criar tipos compostos para casos de uso específicos, como respostas de API que mesclam diferentes estruturas de dados.
Quando Usar Cada uma Desses Métodos
-
Fusão de declaração: Use quando deseja estender ou aprimorar uma interface existente, particularmente em bibliotecas de terceiros ou bases de código compartilhadas.
-
extends
palavra-chave: Use para relacionamentos hierárquicos onde uma interface base pode ser especializada em tipos mais específicos. -
Tipos de interseção (
&
): Use quando você precisa combinar múltiplos tipos não relacionados em um único tipo para casos de uso específicos.
Ao entender essas técnicas de mesclagem e suas implicações, você pode estruturar seu código TypeScript de forma eficaz, melhorando a reutilização e a manutenibilidade enquanto mantém a segurança de tipos.
Empacotamento e Transformações em TypeScript
Nem todos os navegadores suportam o JavaScript mais recente usado pelo TypeScript. Portanto, você pode usar o compilador TypeScript, ou tsc
, para converter código TypeScript (.ts files) em JavaScript convencional (.js files) que seja compatível universalmente com todos os navegadores. O tsc
traduz elementos específicos do TypeScript, como tipos e classes, em código JavaScript que os navegadores podem interpretar.
Para executar arquivos TypeScript, tsc
é a sua escolha. Você pode instalar tsc
usando npm e, em seguida, transformar seus arquivos .ts em arquivos .js. Para usar tsc
, basta especificar o nome do arquivo TypeScript antes do comando tsc
. Por exemplo, se você tiver um arquivo nomeado app.ts
, você pode executá-lo digitando:
tsc app.ts
Webpack ou Parcel são frequentemente utilizados para implantar código TypeScript em navegadores. Essas ferramentas agrupam todos os arquivos JavaScript, incluindo aqueles do TypeScript, para melhorar o desempenho e facilitar a implementação do site. Elas também otimizam o carregamento do código reduzindo seu tamanho e aumentando a velocidade do navegador.
Construindo Código Melhor com TypeScript
Abrace o TypeScript como um desenvolvedor JavaScript e abra possibilidades para escrever um código mais robusto e fácil de manter. Ao entender os fundamentos e conceitos básicos delineados neste guia, você pode aproveitar o sistema de tipagem estática do TypeScript para capturar erros cedo no desenvolvimento, resultando em menos bugs e uma manutenção de código mais suave.
Usando TypeScript, os desenvolvedores JavaScript podem melhorar a qualidade e a produtividade do seu código. À medida que você continua a explorar e praticar com TypeScript, descobrirá recursos e funcionalidades ainda mais poderosos.
Continue desafiando seus limites e mergulhe mais fundo no mundo do TypeScript. 😉
Source:
https://www.freecodecamp.org/news/start-learning-typescript-beginners-guide/