1. Visão Geral
TypeScript é um superset do JavaScript que adota características de linguagens fortemente tipadas, elevando o desenvolvimento web a um novo patamar de robustez. A relação entre JavaScript, ECMAScript e TypeScript é clara: ECMAScript é o padrão que define o JavaScript, enquanto TypeScript estende o JavaScript com tipagem estática.
2. Benefícios do Uso
Detecção Antecipada de Erros: O JavaScript só identifica falhas durante a execução, mas o TypeScript permite a verificação estática antes da execução, reduzindo bugs comuns.
Correção de Falhas Comuns: Erros como digitação incorreta, funções não invocadas ou lógicas equivocadas são sinalizados pelo TypeScript.
const pessoa = {
nome: 'Ana',
idade: 28
};
pessoa.endereco; // No JavaScript, retorna undefined
// No TypeScript, gera um erro: propriedade 'endereco' não definida
function calcularMedia() {
return Math.random < 0.5; // Falta () após Math.random
// O TypeScript indica erro: chamada de função ausente
}
const resultado = Math.random() < 0.5 ? 'x' : 'y';
if (resultado !== 'x') { // O TypeScript alerta que esta condição é sempre falsa
// Código nunca executado
} else if (resultado === 'y') {
// Código também inacessível
}
3. Configuração e Uso
Ambiente: Utilize editores como VS Code, Node.js e o compilador TypeScript (intsalado via npm).
Otimização da Compilação: Para resolver conflitos entre arquivos .ts e .js, como declarações duplicadas de variáveis ou funções, gere um arquivo de confgiuração com tsc --init.
Controle de Erros: Desative o modo estrito no tsconfig.json com strict: false para ignorar certas verificações de tipo.
Compilação Contínua: Use tsc --watch para recompilar automaticamente ao salvar alterações. Para interromper a compilação em caso de erros, execute tsc --noEmitOnError arquivo.ts.
Anotações de Tipo:
function saudar(usuario: string, data: Date): void {
console.log(usuario, data);
}
// A chamada deve corresponder aos tipos; o TypeScript infere tipos automaticamente
saudar('Carlos', new Date()); // Erro: new Date() é inferido como Date, não string
Inferência Automática de Tipos:
const mensagem = 'Olá'; // Tipo inferido como string
mensagem = 123; // Erro: não é possível atribuir number a string
function definirIdade(idade: 24 | 25 | 26) { // Restrição a valores específicos
// ...
}
const individuo = {
nome: 'Maria',
idade: 25 // Inferido como number (qualquer número)
};
definirIdade(individuo.nome, individuo.idade); // Erro: idade não é do tipo 24|25|26
definirIdade(individuo.nome, individuo.idade as 26); // Asserção de tipo para corrigir
Compilação para Compatibilidade: No tsconfig.json, altere "target": "es2016" para "es5" para gerar código compatível com navegadores mais antigos.
4. Sistema de Tipos
Tipos Básicos: string (cadeia de caracteres), number (número), boolean (verdadeiro/falso), null (valor nulo), undefined (valor indefinido).
any: Aceita qualquer tipo, desativando verificações (usado com cautela).
unknown: Tipo seguro para valores desconhecidos, exigindo verificações antes do uso.
Outros: bigint (números grandes), symbol (símbolos únicos), never (representa estados imposíveis).
Arrays:
let numeros: number[] = [1, 2, 3];
let nomes: Array<string> = ['Ana', 'João']; // Sintaxe genérica
Funções:
function multiplicar(a: number, b: number): number { // Parâmetros e retorno tipados
return a * b;
}
// Função anônima com inferência contextual
const frutas = ['maçã', 'banana', 'laranja'];
frutas.forEach((fruta) => { // Tipo de 'fruta' inferido como string
console.log(fruta.toUpperCase());
});
type FuncaoTransformadora = {
(valor: number): string;
};
function aplicarTransformacao(fn: FuncaoTransformadora, entrada: number): string {
return fn(entrada);
}
Objetos:
function exibirPerfil(perfil: { nome: string; email?: string }) { // 'email' opcional
console.log(perfil.email?.toLowerCase()); // Operador opcional
}
Tipos de União:
function processarId(id: number | string): void {
console.log(id);
}
processarId(101); // Aceita number
processarId('202'); // Aceita string
Aliases de Tipo:
type Produto = {
nome: string;
preco: number;
};
const item: Produto = { nome: 'Livro', preco: 49.9 };
Extensão de Aliases com &:
type Animal = {
especie: string;
};
type Cachorro = Animal & {
raca: string;
};
const rex: Cachorro = { especie: 'Cão', raca: 'Labrador' };
Interfaces:
interface Coordenada {
x: number;
y: number;
}
const ponto: Coordenada = { x: 5, y: 10 };
Extensão com extends:
interface Veiculo {
marca: string;
}
interface Carro extends Veiculo {
portas: number;
}
const sedan: Carro = { marca: 'Toyota', portas: 4 };
Declarações Mergidas: Interfaces com o mesmo nome são combinadas; aliases de tipo não.
interface Configuracao {
tema: string;
}
interface Configuracao {
idioma: string;
}
const config: Configuracao = { tema: 'escuro', idioma: 'pt-BR' };
Assertions de Tipo:
const elemento = document.getElementById('canvas') as HTMLCanvasElement;
const outroElemento = <HTMLCanvasElement>document.getElementById('canvas');
Tipos Literais:
function mover(direcao: 'esquerda' | 'direita'): void {
// ...
}
mover('esquerda'); // Válido
mover('cima'); // Erro
function retornaBinario(valor: string): 0 | 1 {
return valor === 'sim' ? 0 : 1;
}
Enumerações:
enum NivelPrioridade {
Baixa = 1,
Media,
Alta,
Urgente
}
console.log(NivelPrioridade.Media); // 2
Estreitamento de Tipos: Uso de condicionais (como if e switch) para reduzir tipos.
function processarValor(valor: number | string): void {
if (typeof valor === 'number') {
// Aqui, valor é number
} else {
// Aqui, valor é string
}
}
Assinaturas de Construtor:
class Servico {
url: string;
constructor(url: string) {
this.url = url;
}
}
type ConstrutorServico = {
new (url: string): Servico;
};
function instanciarServico(classe: ConstrutorServico, link: string): Servico {
return new classe(link);
}
const servico = instanciarServico(Servico, 'https://api.example.com');
console.log(servico.url);
Funções Genéricas:
function pegarPrimeiro<T>(lista: T[]): T | undefined {
return lista[0];
}
pegarPrimeiro([]); // T inferido como undefined
pegarPrimeiro(['a', 'b']); // T inferido como string
pegarPrimeiro([1, 2, 3]); // T inferido como number
function transformarArray<Entrada, Saida>(
arr: Entrada[],
transformador: (item: Entrada) => Saida
): Saida[] {
return arr.map(transformador);
}
transformarArray(['1', '2'], (n) => parseInt(n)); // Entrada: string, Saida: number