Table of Contents
Curso de TypeScript Profissional 🚀
Bem-vindo ao curso definitivo para dominar o TypeScript no mundo real. Do zero absoluto até arquiteturas complexas, prepare-se para elevar sua carreira de desenvolvedor.
Diferencial
Foco em Engenharia: Não apenas sintaxe, mas como estruturar projetos escaláveis, usar padrões de projeto e garantir a qualidade com testes rigorosos.
🎯 O Que Você Vai Aprender
-
Segurança Extrema
Elimine erros de "undefined" e bugs em tempo de execução com tipagem estática rigorosa.
-
Fullstack Types
Aprenda a compartilhar tipos entre Node.js (Backend) e React (Frontend) com maestria.
-
:material-architecture: Arquitetura Limpa
Domine SOLID, DDD e Padrões de Projeto aplicados ao ecossistema TypeScript.
-
Projetos Reais
Saia da teoria com 16 mini-projetos práticos e um projeto final completo com Deploy.
📚 Estrutura do Curso (16 Aulas)
O curso é dividido em dois módulos estratégicos.
Módulo 1: Core & Linguagem (Aulas 01-08)
Construa sua base sólida na linguagem TypeScript. * Aula 01 - Introdução e Setup Profissional 🧠 * Aula 02 - Tipos Fundamentais e Inferência 🛠️ * Aula 03 - Tipos Avançados (Unions & Guards) 🧩 * Aula 04 - Interfaces e Modelagem 🏗️ * Aula 05 - Classes e Orientação a Objetos 🏛️ * Aula 06 - Generics (Programação Genérica) 📦 * Aula 07 - Utility Types (Produtividade) ⚙️ * Aula 08 - Manipulação Avançada de Tipos 🧪
Módulo 2: Aplicações & Ecossistema (Aulas 09-16)
Aplique o TypeScript no mercado de trabalho real. * Aula 09 - Módulos e Organização 📁 * Aula 10 - Backend com Node.js 🟢 * Aula 11 - Frontend com React ⚛️ * Aula 12 - APIs e Validação (Zod) 📡 * Aula 13 - Testes Automatizados (Jest) 🧪 * Aula 14 - Padrões de Projeto (Design Patterns) 🛡️ * Aula 15 - Clean Code e Arquitetura 📐 * Aula 16 - Projeto Final e Deploy 🚀
Success
Pronto para elevar seu nível? Clique no botão abaixo e inicie sua jornada profissional!
Sobre o Curso
🎓 TypeScript Profissional: Do Core à Arquitetura
Este é um curso completo e estruturado para quem deseja dominar o TypeScript no cenário real do desenvolvimento moderno. Projetado para levar você do setup básico em Node.js até a construção de aplicações complexas com React, APIs robustas e arquiteturas escaláveis.
🎯 Objetivos do Curso
-
Domínio Técnico
Aprender não apenas a sintaxe, mas o "pensamento tipado" (Type Thinking) para modelar sistemas seguros.
-
Ecossistema Real
Integrar TypeScript com as ferramentas mais usadas no mercado: Express, React, Zod, Jest e Docker.
-
Qualidade de Software
Aplicar princípios de Clean Code, SOLID e Design Patterns para criar códigos fáceis de manter por equipes.
-
Engenharia de Dados
Dominar Generics, Tipos Avançados e Manipulação de Dados Externos com total segurança e previsibilidade.
📚 O Que Você Vai Aprender
Módulo 1 – Core & Linguagem
- Setup Profissional e Compilação
- Tipos Primitivos, Avançados e Inferência
- Interfaces vs Type Aliases
- Classes, POO e Modificadores de Acesso
- Generics e Utility Types
- Manipulação Dinâmica de Tipos
Módulo 2 – Ecossistema & Arquitetura
- Organização em Módulos e Aliases
- Backend com Node.js e Express
- Frontend Moderno com React
- Integração de APIs e Validação (Zod)
- Testes Automatizados com Jest
- Padrões de Projeto e Clean Code
- Build para Produção e Docker
🛠️ Metodologia
-
Aulas Práticas
Conteúdo focado em cenários de código real, com diagramas Mermaid para facilitar a compreensão.
-
80 Exercícios
Listas graduadas (Básico, Médio, Desafio) para fixar cada conceito da linguagem.
-
16 Mini-Projetos
Saia da aula com algo pronto: desde calculadoras tipadas até APIs e Dashboards completos.
-
Quizzes Detalhados
Avalie seu progresso com 160 questões comentadas em português.
👨🎓 Para Quem é Este Curso
- Desenvolvedores JS que querem evitar bugs e subir de nível profissional
- Estudantes que buscam uma base sólida de Engenharia de Software
- Profissionais que pretendem trabalhar em grandes empresas de tecnologia
- Arquitetos de Software que precisam padronizar códigos escaláveis
📋 Pré-requisitos
- Conhecimento básico de lógica e JavaScript
- Node.js instalado (coberto no curso)
- Editor de código (VS Code recomendado)
- Vontade de escrever código de alta qualidade!
🎖️ O Que Você Receberá
- ✅ 16 aulas completas e atualizadas
- ✅ Slides interativos para todas as aulas
- ✅ 80 exercícios práticos com soluções
- ✅ 16 mini-projetos para portfólio
- ✅ 160 questões de quiz com explicações
- ✅ Guia de Deploy e Dockerização
🚀 Comece Agora
Pronto para dominar o TypeScript?
Dúvidas? Explore o Roadmap do Projeto ou comece agora mesmo!
Aulas
Aulas do Curso 📚
Acesse aqui todo o conteúdo teórico dividido em dois grandes blocos: Core da Linguagem e Aplicações do Ecossistema.
-
Módulo 1: Core & Linguagem
A base sólida para escrever código seguro e previsível. Do setup até manipulação avançada.
- Aula 01 - Introdução e Setup Profissional
- Aula 02 - Tipos Fundamentais e Inferência
- Aula 03 - Tipos Avançados (Unions & Guards)
- Aula 04 - Interfaces e Modelagem
- Aula 05 - Classes e Orientação a Objetos
- Aula 06 - Generics (Programação Genérica)
- Aula 07 - Utility Types (Produtividade)
- Aula 08 - Manipulação Avançada de Tipos
-
Módulo 2: Ecossistema & Aplicações
Aplicação prática do TypeScript em ferramentas e frameworks de mercado.
Aula 01 - Introdução ao TypeScript e Setup Profissional 🧠
Objetivo
Nesta aula, você entenderá a evolução do JavaScript, por que o TypeScript se tornou o padrão da indústria e como configurar um ambiente de desenvolvimento profissional do zero.
1. Evolução do JavaScript e Problemas da Tipagem Dinâmica 🌊
O JavaScript nasceu em 1995 para ser uma linguagem de scripts simples para navegadores. Com o passar dos anos, ele assumiu o controle de aplicações complexas (Gmail, Facebook, VS Code). No entanto, sua natureza dinâmica e fracamente tipada traz desafios em larga escala.
O Problema da Tipagem Dinâmica 🧨
Em JS, você pode fazer isso:
Erros como undefined is not a function ou cannot read property of null são comuns e só aparecem em tempo de execução (quando o usuário está usando o app).
Atenção
Erros silenciosos em JavaScript são a maior causa de bugs em produção. O TypeScript resolve isso movendo a detecção de erros para o tempo de compilação.
2. O que é TypeScript? 🛡️
O TypeScript é um superset (superconjunto) do JavaScript criado pela Microsoft. Isso significa que todo código JavaScript é um código TypeScript válido, mas o TS adiciona uma camada de tipagem estática.
Por que usar TypeScript?
- Segurança: Detecta erros antes de rodar o código.
- Autocompletar (IntelliSense): O VS Code "entende" seu código e sugere propriedades.
- Refatoração: É muito mais seguro mudar nomes de funções ou variáveis em projetos grandes.
3. Setup Profissional 🛠️
Para começar, precisamos do Node.js instalado. O TypeScript é instalado via NPM (Node Package Manager).
Instalação Global
Conceito
O comando tsc é o TypeScript Compiler. Ele transforma seu código .ts em código .js que o navegador ou o Node conseguem entender.
4. O Coração do Projeto: tsconfig.json ⚙️
Todo projeto sério de TypeScript possui um arquivo de configuração chamado tsconfig.json. Ele define como o compilador deve se comportar.
Criando a Configuração
Dica
No tsconfig.json, ative sempre o "strict": true para garantir o máximo de segurança e as melhores práticas da linguagem.
5. Primeiro Projeto Estruturado (Laboratório) 🧪
Vamos criar nossa primeira estrutura profissional:
- Crie uma pasta
src/(onde ficará o código fonte). - Crie um arquivo
src/index.ts.
Visualizando o Fluxo de Trabalho (Mermaid)
graph LR;
TS[Código TypeScript .ts] -- "Compilador (tsc)" --> JS[Código JavaScript .js];
JS -- "Execução" --> Node[Node.js / Navegador];
style TS fill:#3178c6,color:#fff
style JS fill:#f7df1e,color:#000
Exemplo de Código no VS Code
interface Usuario {
nome: string;
id: number;
}
const novoUsuario: Usuario = {
nome: "Ricardo",
id: 1
};
console.log(`Olá, ${novoUsuario.nome}! Seu ID é ${novoUsuario.id}.`);
6. Exercícios de Fixação 📝
- Básico: Instale o TypeScript na sua máquina e verifique a versão.
- Básico: Crie um arquivo
ola.ts, declare uma variávelmsg: stringe imprima no console. - Intermediário: Gere o arquivo
tsconfig.jsone mude a opçãotargetparaES6. O que isso muda no JS gerado? - Intermediário: Tente atribuir um número a uma variável declarada como string. Observe o erro no VS Code.
- Desafio: Configure um script no
package.jsonchamadobuildque execute o comandotsc.
🚀 Mini-Projeto da Aula
Configure um ambiente onde o comando tsc -w (watch mode) fique monitorando sua pasta src/ e compilando automaticamente para uma pasta dist/.
Próxima Aula: Vamos mergulhar nos Tipos Fundamentais e Inferência e entender como o TS "adivinha" nossos tipos!
Aula 02 - Tipos Fundamentais e Inferência 🛠️
Objetivo
Nesta aula, exploraremos os pilares da tipagem no TypeScript: os tipos primitivos, as estruturas de dados básicas e o poderoso sistema de inferência que torna o código limpo e seguro ao mesmo tempo.
1. Tipos Primitivos 🧱
O TypeScript herda os tipos primitivos do JavaScript, mas permite que você os declare explicitamente.
| Tipo | Descrição | Exemplo |
|---|---|---|
string |
Textos | "Olá mundo" |
number |
Números (inteiros e decimais) | 42 ou 3.14 |
boolean |
Valores lógicos | true ou false |
Exemplo de Declaração
2. Arrays e Tuplas 📊
Arrays
Existem duas formas de declarar arrays:
Tuplas
As Tuplas permitem declarar um array com um número fixo de elementos e tipos conhecidos em posições específicas.
let pessoa: [string, number];
pessoa = ["Ricardo", 30]; // ✅ Correto
// pessoa = [30, "Ricardo"]; // ❌ Erro: Tipos na ordem errada
3. Enum, Any e Unknown 🎭
Enum
Permite definir um conjunto de constantes nomeadas, facilitando a legibilidade.
Any vs Unknown
Atenção
O tipo any desativa a checagem de tipos. Use apenas em casos extremos de migração de código.
any: Aceita qualquer coisa e permite qualquer operação.unknown: Aceita qualquer coisa, mas obriga você a verificar o tipo antes de usar (mais seguro).
4. Void e Never 🚫
void: Usado em funções que não retornam nenhum valor.never: Usado em funções que nunca terminam (como loops infinitos) ou que sempre lançam exceções.
function avisar(): void {
console.log("Aviso enviado!");
}
function erroFatal(msg: string): never {
throw new Error(msg);
}
5. Inferência de Tipos 🧠
O TypeScript é inteligente o suficiente para entender o tipo de uma variável sem que você precise escrever.
let curso = "TypeScript"; // O TS infere automaticamente que 'curso' é string
// curso = 10; // ❌ Erro: Não posso atribuir número a uma string
6. Strict Mode: O Coração da Qualidade 🛡️
Como vimos na Aula 1, o tsconfig.json possui o strict mode. Ele força o desenvolvedor a lidar com valores null e undefined, evitando os famosos erros de "quebra" em produção.
Visualizando a Hierarquia de Tipos (Mermaid)
graph TD;
Top[unknown / any] --> Prim[Primitivos];
Prim --> string;
Prim --> number;
Prim --> boolean;
Top --> Obj[Arrays / Objetos / Tuplas];
Obj --> Void[void];
Void --> Never[never];
7. Exercícios Práticos 📝
- Básico: Crie uma variável para cada tipo primitivo e atribua valores coerentes.
- Básico: Crie um array de strings e uma tupla contendo o nome e a versão de um software.
- Intermediário: Crie um
enumpara representar os dias da semana. - Intermediário: Crie uma função que receba um parâmetro
unknowne use otypeofpara imprimir se é uma string ou número. - Desafio: Tente criar uma função que retorne
nevere explique em qual cenário do mundo real ela seria útil.
🚀 Mini-Projeto da Aula
Crie um pequeno script de "Gerenciamento de Inventário" onde cada item é uma tupla [id: number, nome: string, preco: number, emEstoque: boolean]. Use um enum para as categorias dos itens.
Próxima Aula: Vamos aprender sobre Tipos Avançados como Union Types e Type Guards!
Aula 03 – Tipos Avançados 🧩
Objetivo
Nesta aula, aprenderemos a criar tipos flexíveis e poderosos usando uniões, interseções e aliases. Também veremos como o TypeScript nos ajuda a "estreitar" os tipos para garantir que o código seja 100% seguro contra erros de runtime.
1. Union Types (|) 🔗
O Union Type permite que uma variável tenha mais de um tipo possível. É como dizer: "esta variável pode ser uma string OU um número".
function imprimirId(id: number | string) {
console.log(`Seu ID é: ${id}`);
}
imprimirId(101); // ✅ OK
imprimirId("202"); // ✅ OK
// imprimirId(true); // ❌ Erro: boolean não é permitido
2. Type Alias 🏷️
Em vez de repetir tipos complexos em vários lugares, podemos criar um "apelido" usando a palavra-chave type.
3. Intersection Types (&) 🤝
Enquanto a união é um "ou", a interseção é um "e". Ela combina múltiplos tipos em um só. É muito usada para compor objetos.
type Pessoa = { nome: string };
type Empregado = { cargo: string };
type Desenvolvedor = Pessoa & Empregado;
const ricardo: Desenvolvedor = {
nome: "Ricardo",
cargo: "Tech Lead"
};
4. Literal Types 🎯
Podemos definir valores exatos que uma variável pode assumir. Isso é excelente para estados ou configurações.
type Alinhamento = "esquerda" | "centro" | "direita";
let texto: Alinhamento = "centro"; // ✅ OK
// texto = "cima"; // ❌ Erro: "cima" não está na lista
5. Narrowing e Type Guards 🛡️
Narrowing (Estreitamento) é o processo de o TypeScript "entender" qual é o tipo exato dentro de um fluxo lógico. Isso é feito usando Type Guards.
Exemplo com typeof
function processar(entrada: string | number) {
if (typeof entrada === "string") {
console.log(entrada.toUpperCase()); // Aqui o TS sabe que é string
} else {
console.log(entrada.toFixed(2)); // Aqui o TS sabe que é number
}
}
6. Estudo de Caso: Validação de Dados de API 📡
Ao receber dados de uma API, muitas vezes não sabemos o formato exato. Usar tipos avançados nos protege.
Visualizando a Validação (Mermaid)
graph TD;
API[Resposta da API] --> Guard{É um Usuário?};
Guard -- Sim --> Success[Acessar propriedades .nome e .id];
Guard -- Não --> Error[Tratar erro de formato];
style Guard fill:#f96,stroke:#333
7. Exercícios Práticos 📝
- Básico: Crie um Type Alias chamado
Statusque aceite os literais "ativo", "pendente" ou "inativo". - Básico: Crie uma função que receba um parâmetro que pode ser
numberounulle retorne o dobro se for número ou 0 se for null. - Intermediário: Crie dois tipos,
CarroeEletrico, e use uma interseção para criar umCarroEletrico. - Intermediário: Use o operador
incomo Type Guard para verificar se uma propriedade existe em um objeto. - Desafio: Crie uma função de validação de API que receba um objeto
anye use Type Guards para transformá-lo em um tipoProdutoseguro.
🚀 Mini-Projeto da Aula
Crie um sistema de "Notificações". O sistema deve aceitar notificações por Email ou SMS.
- Email tem endereco e assunto.
- SMS tem numero e mensagem.
Use Union Types e Narrowing para processar o envio corretamente.
Próxima Aula: Vamos explorar Interfaces e Modelagem de Domínio e entender a diferença entre interface e type!
Aula 04 – Interfaces e Modelagem de Domínio 🏗️
Objetivo
Nesta aula, aprenderemos a modelar objetos complexos usando Interfaces. Entenderemos a diferença entre interface e type e como construir contratos sólidos para aplicações corporativas.
1. O que são Interfaces? 📜
Uma Interface é um contrato que define a estrutura de um objeto. Ela diz quais propriedades e métodos um objeto deve ter, mas não como eles são implementados.
interface Livro {
titulo: string;
autor: string;
paginas?: number; // Propriedade opcional
readonly isbn: string; // Propriedade apenas de leitura
}
const meuLivro: Livro = {
titulo: "Clean Code",
autor: "Robert C. Martin",
isbn: "123-456-789"
};
2. Extensão de Interfaces (Herança de Contratos) 🧬
Podemos combinar interfaces para criar estruturas mais complexas e reutilizáveis.
interface Animal {
nome: string;
}
interface Mamifero extends Animal {
amamentar(): void;
}
const cachorro: Mamifero = {
nome: "Rex",
amamentar: () => console.log("Amamentando...")
};
3. Implementação em Classes 🏛️
As interfaces são fundamentais na Programação Orientada a Objetos (POO). Uma classe pode "assinar" um contrato de interface usando a palavra-chave implements.
interface Autenticavel {
login(): boolean;
}
class Usuario implements Autenticavel {
login(): boolean {
console.log("Usuário logado!");
return true;
}
}
4. Diferença entre Interface e Type Alias ⚖️
Ambos são muito parecidos, mas existem diferenças fundamentais:
| Característica | Interface | Type Alias |
|---|---|---|
| Extensibilidade | Pode ser estendida via extends. |
Pode ser combinada via interseção (&). |
| Declaration Merging | Se você definir duas com o mesmo nome, elas se fundem. | Não permite nomes duplicados. |
| Ideal para | Modelagem de objetos e POO. | Uniões, Primitivos, Funções e Tipos complexos. |
Dica Profissional
A recomendação oficial do TypeScript é: use Interface até que você precise de uma funcionalidade específica do Type.
5. Modelagem de Domínio (Entidades) 🗺️
Modelar o domínio é definir as "regras de negócio" através dos tipos. Em um e-commerce, teríamos:
Visualizando o Domínio (Mermaid)
classDiagram
class Produto {
+number id
+string nome
+number preco
}
class Cliente {
+string email
+string endereco
}
class Pedido {
+Produto[] itens
+Cliente cliente
+total() number
}
Pedido o-- Produto : contém
Pedido o-- Cliente : pertence a
6. Exercícios Práticos 📝
- Básico: Crie uma interface
Funcionariocom propriedadesnome,salarioe uma propriedade opcionalbonus. - Básico: Crie uma interface
Veiculoe useextendspara criar uma interfaceMoto. - Intermediário: Tente usar o "Declaration Merging" criando duas interfaces
Usuarioem partes diferentes do código e veja como o TS as une. - Intermediário: Crie uma interface para uma função que recebe dois números e retorna a soma deles.
- Desafio: Modele um sistema de biblioteca. Crie interfaces para
Autor,LivroeEmprestimo. Garanta que um empréstimo tenha uma data de início e uma data de devolução.
🚀 Mini-Projeto da Aula
Modele as entidades de um Sistema de Gestão Acadêmica.
- Interfaces para: Aluno, Professor, Disciplina e Turma.
- Uma turma deve conter um professor e uma lista de alunos.
- Utilize propriedades readonly para IDs que não podem ser alterados.
Próxima Aula: Vamos subir o nível com Classes e Programação Orientada a Objetos no TypeScript!
Aula 05 – Classes e Programação Orientada a Objetos 🏛️
Objetivo
Nesta aula, aplicaremos os conceitos de Programação Orientada a Objetos (POO) no TypeScript. Veremos como encapsular dados, usar modificadores de acesso e criar abstrações poderosas para sistemas escaláveis.
1. Modificadores de Acesso 🔒
Diferente do JavaScript puro, o TypeScript oferece modificadores que controlam quem pode acessar as propriedades e métodos de uma classe.
| Modificador | Descrição |
|---|---|
public |
(Padrão) Acesso total de qualquer lugar. |
private |
Acesso apenas dentro da própria classe. |
protected |
Acesso dentro da classe e de suas subclasses (herança). |
class ContaBancaria {
private saldo: number = 0; // Ninguém fora da classe mexe aqui
public depositar(valor: number): void {
this.saldo += valor;
}
}
2. Parâmetros Readonly e Shorthand Syntax ⚡
O TypeScript nos permite declarar e inicializar propriedades diretamente no construtor.
class Usuario {
constructor(
public readonly id: number,
private nome: string
) {}
}
const u = new Usuario(1, "Ricardo");
// u.id = 2; // ❌ Erro: Propriedade é readonly
3. Getters e Setters 🔄
Permitem aplicar lógica ao ler ou alterar um valor.
class Produto {
private _preco: number = 0;
get preco() { return this._preco; }
set preco(valor: number) {
if (valor < 0) throw new Error("Preço inválido!");
this._preco = valor;
}
}
4. Herança e Polimorfismo 🧬
A herança permite que uma classe herde comportamentos de outra, facilitando a reutilização de código.
class Funcionario {
constructor(public nome: string) {}
getBonus() { return 1000; }
}
class Gerente extends Funcionario {
getBonus() { return super.getBonus() + 5000; } // Polimorfismo
}
5. Classes Abstratas ☁️
Uma classe abstrata não pode ser instanciada diretamente. Ela serve como um "esqueleto" para outras classes.
Visualizando a Abstração (Mermaid)
classDiagram
class Pagamento {
<<abstract>>
+number valor
+processar()* void
}
class Cartao {
+processar() void
}
class Boleto {
+processar() void
}
Pagamento <|-- Cartao
Pagamento <|-- Boleto
6. Exercícios Práticos 📝
- Básico: Crie uma classe
Carrocom propriedadesmarca,modeloe um métodoacelerar. - Básico: Use o modificador
privateem uma propriedadevelocidadee crie um getter para ela. - Intermediário: Crie uma classe
Animalabstrata com um método abstratofazerSom()e implemente-o nas classesCachorroeGato. - Intermediário: Crie uma classe
Pessoae uma subclasseEstudante. Use osuper()no construtor da subclasse. - Desafio: Crie um sistema de "Contas". Uma
Contaabstrata e subclassesContaCorrenteeContaPoupanca. AContaCorrentedeve cobrar uma taxa em cada saque.
🚀 Mini-Projeto da Aula
Desenvolva um Sistema de RPG Simples.
- Crie uma classe base Personagem com nome, vida e ataque.
- Crie subclasses Guerreiro (mais vida) e Mago (mais ataque).
- Use encapsulamento para garantir que a vida nunca fique negativa.
Próxima Aula: Vamos aprender sobre Generics e como criar código que funciona com qualquer tipo!
Aula 06 – Generics (Programação Genérica) 📦
Objetivo
Nesta aula, desvendaremos o poder dos Generics. Você aprenderá a criar códigos altamente reutilizáveis e flexíveis que mantêm a segurança de tipos, independentemente do dado que estão processando.
1. O que são Generics? 🧬
Generics permitem que componentes (funções, classes ou interfaces) funcionem com uma variedade de tipos, ao invés de apenas um. Pense neles como "parâmetros para tipos".
O problema sem Generics
function retornarPrimeiro(lista: any[]): any {
return lista[0];
}
// ❌ Perdemos a informação do tipo original
A solução com Generics
function retornarPrimeiro<T>(lista: T[]): T {
return lista[0];
}
const n = retornarPrimeiro([1, 2, 3]); // n é inferido como number
const s = retornarPrimeiro(["a", "b"]); // s é inferido como string
2. Constraints (Restrições) ⛓️
Nem sempre queremos que o Generic aceite "qualquer" tipo. Podemos restringir o que ele aceita usando a palavra-chave extends.
interface TemComprimento {
length: number;
}
function logComprimento<T extends TemComprimento>(obj: T) {
console.log(obj.length);
}
logComprimento("Olá"); // ✅ OK (string tem length)
logComprimento([1, 2]); // ✅ OK (array tem length)
// logComprimento(10); // ❌ Erro: number não tem length
3. Classes Genéricas 🏗️
Classes também podem se beneficiar dessa flexibilidade. Um exemplo comum são as Pilhas ou Filas.
class Caixa<T> {
private conteudo?: T;
guardar(item: T) { this.conteudo = item; }
pegar() { return this.conteudo; }
}
const caixaDeNumeros = new Caixa<number>();
caixaDeNumeros.guardar(10);
4. Generics com Interfaces 📜
Podemos tornar nossas interfaces adaptáveis a diferentes tipos de resposta, muito comum em APIs.
interface RespostaAPI<T> {
data: T;
erro: string | null;
}
const respostaUsuario: RespostaAPI<{nome: string}> = {
data: { nome: "Ricardo" },
erro: null
};
5. Visualizando o Fluxo Genérico (Mermaid)
graph LR;
Entrada[Dados de Qualquer Tipo] --> Funcao{Função Genérica < T >};
Funcao --> Saída[Mantém o Tipo Original T];
style Funcao fill:#bbf,stroke:#333
6. Exercícios Práticos 📝
- Básico: Crie uma função genérica
identidade<T>que receba um argumento de tipoTe retorne exatamente esse argumento. - Básico: Crie um array genérico de strings.
- Intermediário: Crie uma função genérica que receba dois argumentos e retorne um array contendo ambos.
- Intermediário: Use constraints para garantir que um tipo genérico possua a propriedade
id: number. - Desafio: Crie uma interface
ListaPaginada<T>que contenha um array deitens: T[]e uma propriedadetotal: number.
🚀 Mini-Projeto da Aula
Crie um Repositório Genérico de Dados.
- O repositório deve ter métodos para: salvar(item: T), obterTodos(): T[] e buscarPorId(id: number): T | undefined.
- Teste o repositório criando uma instância para Produtos e outra para Usuarios.
Próxima Aula: Vamos explorar os Utility Types e descobrir como transformar tipos existentes de forma mágica!
Aula 07 – Utility Types e Manipulação de Tipos ⚙️
Objetivo
Nesta aula, conheceremos os utilitários integrados do TypeScript que facilitam a transformação de tipos existentes. Eles são essenciais para manter o código DRY (Don't Repeat Yourself) e flexível.
1. O que são Utility Types? 🛠️
Os Utility Types são tipos globais fornecidos pelo TypeScript que permitem realizar mapeamentos e transformações comuns de forma simples e segura.
2. Utilitários de Propriedades 📋
Partial
Torna todas as propriedades de um tipo opcionais. Útil para atualizações parciais de dados.
interface Usuario {
id: number;
nome: string;
email: string;
}
const atualizar: Partial<Usuario> = { nome: "Novo Nome" };
Required
O oposto do Partial. Torna todas as propriedades obrigatórias.
Readonly
Torna todas as propriedades apenas de leitura, impedindo alterações após a atribuição inicial.
3. Utilitários de Seleção ✂️
Pick
Cria um novo tipo escolhendo apenas algumas propriedades do tipo original.
Omit
Cria um novo tipo removendo as propriedades especificadas.
4. Utilitários de Estrutura 🏗️
Record
Cria um tipo de objeto onde as chaves são do tipo K e os valores são do tipo T.
type Configuracoes = Record<"tema" | "idioma", string>;
const config: Configuracoes = {
tema: "dark",
idioma: "pt-BR"
};
5. Mapped Types (Breve Introdução) 🗺️
Os Utility Types acima são construídos usando Mapped Types. Eles permitem que você percorra as propriedades de um tipo e crie um novo.
Visualizando a Transformação (Mermaid)
graph LR;
Original[Interface Original] -- "Partial< T >" --> Opcional[Todas Opcionais];
Original -- "Pick< T, K >" --> Selecionado[Apenas Algumas];
Original -- "Readonly< T >" --> Protegido[Apenas Leitura];
style Original fill:#e1f5fe,stroke:#01579b
6. Exercícios Práticos 📝
- Básico: Use
Partialpara criar uma função que aceite uma atualização parcial de um objetoProduto. - Básico: Crie uma interface
Configcom propriedades opcionais e useRequiredpara garantir que todas estejam presentes em uma variável. - Intermediário: Use
Pickpara extrair apenas otituloe adatade uma interfacePost. - Intermediário: Use
Recordpara criar um dicionário de traduções onde as chaves são "ola" e "tchau" e os valores são strings. - Desafio: Combine
OmiteReadonlypara criar um tipo de dado que não contenha o ID de umUsuarioe seja imutável.
🚀 Mini-Projeto da Aula
Crie um Transformador de Modelos.
- Defina uma interface robusta para um Pedido.
- Crie um tipo para a visualização resumida do pedido (Pick).
- Crie um tipo para a criação de um pedido (onde campos como id e dataGeracao são omitidos via Omit).
- Garanta que os dados da API sejam de apenas leitura (Readonly).
Próxima Aula: Vamos mergulhar na Manipulação Avançada de Tipos e entender tipos condicionais e o operador infer!
Aula 08 – Manipulação Avançada de Tipos 🧪
Objetivo
Nesta aula, exploraremos as funcionalidades mais avançadas do sistema de tipos do TypeScript. Aprenderemos a criar tipos que dependem de condições, extrair tipos de funções e gerar strings de tipos dinamicamente.
1. keyof e Indexed Access Types 🔑
Operador keyof
O operador keyof obtém todas as chaves de um tipo de objeto e as transforma em uma união de literais.
interface Carro {
marca: string;
ano: number;
}
type ChavesDoCarro = keyof Carro; // "marca" | "ano"
Indexed Access Types
Permite acessar o tipo de uma propriedade específica de outro tipo.
2. Tipos Condicionais 🛠️
Funcionam como um "if" para tipos. A sintaxe é similar ao operador ternário.
type EString<T> = T extends string ? "Sim" : "Não";
type Teste1 = EString<string>; // "Sim"
type Teste2 = EString<number>; // "Não"
3. O Operador infer 🔍
Usado dentro de tipos condicionais para "inferir" e extrair um tipo de dentro de outro (como o tipo de retorno de uma função).
type RetornoDeFuncao<T> = T extends (...args: any[]) => infer R ? R : any;
function soma(a: number, b: number): number { return a + b; }
type ResultadoSoma = RetornoDeFuncao<typeof soma>; // number
4. Template Literal Types 🖋️
Permitem criar novos tipos de string baseados em uniões de strings, usando a mesma sintaxe de template strings do JS.
type Cor = "vermelho" | "azul";
type Intensidade = "claro" | "escuro";
type CorCompleta = `${Cor}-${Intensidade}`;
// "vermelho-claro" | "vermelho-escuro" | "azul-claro" | "azul-escuro"
5. Visualizando a Lógica Condicional (Mermaid)
graph TD;
T[Tipo T] --> Cond{T extends U?};
Cond -- Verdadeiro --> X[Tipo X];
Cond -- Falso --> Y[Tipo Y];
style Cond fill:#f9f,stroke:#333
6. Exercícios Práticos 📝
- Básico: Use
keyofpara criar uma função que receba um objeto e uma de suas chaves e retorne o valor daquela chave. - Básico: Use
Indexed Access Typespara obter o tipo de um elemento dentro de um array de strings. - Intermediário: Crie um tipo condicional que verifique se um tipo é um array. Se for, retorne o tipo dos itens; se não, retorne o próprio tipo.
- Intermediário: Use
Template Literal Typespara gerar todas as combinações de chaves de um objeto CSS (ex:margin-top,margin-bottom, etc.). - Desafio: Use
inferpara criar um tipo que extraia o tipo do primeiro argumento de uma função.
🚀 Mini-Projeto da Aula
Crie um Gerador de Tipos Dinâmicos para APIs.
- Use Template Literal Types para criar rotas de API baseadas em recursos (ex: get-user, post-user).
- Use tipos condicionais para definir se a resposta de uma função deve ser um objeto ou um erro mapeado.
- Utilize keyof para validar se os filtros de busca enviados para a API pertencem ao modelo de dados.
Próxima Aula: Vamos organizar nossos projetos em Módulos e Organização Profissional de forma escalável!
Aula 09 – Módulos e Organização Profissional 📁
Objetivo
Nesta aula, aprenderemos a organizar código TypeScript de forma modular e escalável. Veremos como usar ES Modules, criar "Barrel Files" e configurar apelidos para caminhos, facilitando a manutenção de projetos grandes.
1. ES Modules (import/export) 📦
O TypeScript segue o padrão oficial do JavaScript para módulos (ESM). Isso permite que dividamos o código em vários arquivos e importemos apenas o que for necessário.
Exportando
Importando
2. Barrel Files (O arquivo index.ts) 🛢️
Um Barrel File é uma forma de consolidar múltiplos módulos em um único arquivo de saída, simplificando os imports no restante da aplicação.
Estrutura
Exemplo no index.ts
Agora você pode importar tudo de /models em vez de cada arquivo individualmente.
3. Namespaces (Legado vs Moderno) 🏛️
Antigamente, usava-se muito o namespace para organizar o código. Hoje, com o ES Modules, eles são menos comuns, mas ainda aparecem em bibliotecas legadas ou definições de tipos.
4. Path Aliases (Apelidos de Caminho) 🗺️
Em projetos grandes, os imports podem ficar confusos: ../../../../services/api. Podemos configurar o tsconfig.json para criar apelidos.
Configuração no tsconfig.json
{
"compilerOptions": {
"baseUrl": "./src",
"paths": {
"@services/*": ["services/*"],
"@models/*": ["models/*"]
}
}
}
5. Estruturação de Projeto Profissional 🏗️
Visualizando a Estrutura (Mermaid)
graph TD;
Root[Raiz do Projeto] --> Src[src];
Src --> Models[models - Interfaces e Types];
Src --> Services[services - Lógica e APIs];
Src --> Utils[utils - Funções utilitárias];
Src --> App[index.ts - Ponto de Entrada];
Root --> Dist[dist - Código JS Compilado];
Root --> Config[tsconfig.json];
6. Exercícios Práticos 📝
- Básico: Crie dois arquivos: um que exporte uma classe e outro que a importe e instancie.
- Básico: Use o
export defaultpara exportar uma função e importe-a com um nome diferente. - Intermediário: Crie uma pasta
utils, adicione três funções em arquivos separados e crie um "Barrel File" (index.ts) para exportá-las. - Intermediário: Tente configurar um
path aliasno seutsconfig.jsone use-o em um import. - Desafio: Refatore um projeto pequeno que use apenas um arquivo para a estrutura profissional sugerida no diagrama acima.
🚀 Mini-Projeto da Aula
Organize um Sistema de Cadastro de Clientes.
- Crie uma pasta domain para as interfaces.
- Crie uma pasta data para o repositório.
- Crie uma pasta shared para funções utilitárias (ex: formatadores de CPF).
- Use Barrel Files em cada pasta para exportar as funcionalidades de forma limpa.
Próxima Aula: Vamos colocar o TypeScript para rodar no lado do servidor com TypeScript com Node.js (Backend)!
Aula 10 – TypeScript com Node.js (Backend) 🟢
Objetivo
Nesta aula, aprenderemos a utilizar o TypeScript no desenvolvimento backend com Node.js. Veremos como configurar o ambiente, tipar requisições do Express, usar DTOs e garantir a segurança dos dados que entram na nossa API.
1. Configuração do Ambiente Backend 🛠️
Para rodar TypeScript no Node.js de forma eficiente, usamos ferramentas como ts-node-dev para desenvolvimento e tsc para produção.
Instalação das Dependências
O que são @types?
Como muitas bibliotecas JS não foram escritas em TS, a comunidade mantém o repositório DefinitelyTyped. O pacote @types/express fornece as definições de tipo para que o TS entenda o Express.
2. Tipagem de Requisições e Respostas 📨
O Express no TypeScript permite que tipemos os parâmetros, o corpo da requisição e a resposta.
import express, { Request, Response } from 'express';
const app = express();
app.use(express.json());
app.post('/usuarios', (req: Request, res: Response) => {
const { nome } = req.body; // req.body aqui é 'any' por padrão
return res.status(201).json({ mensagem: `Usuário ${nome} criado!` });
});
3. DTOs (Data Transfer Objects) e Validação 🛡️
Para evitar o uso de any e garantir que os dados recebidos são válidos, usamos o padrão DTO.
interface CriarUsuarioDTO {
nome: string;
email: string;
idade: number;
}
app.post('/usuarios', (req: Request, res: Response) => {
const dados: CriarUsuarioDTO = req.body;
// Agora temos autocompletar e segurança de tipos em 'dados'
});
4. Middleware Tipado 🧩
Middlewares são funções que rodam entre a requisição e a resposta. Eles também devem ser tipados.
import { NextFunction } from 'express';
function loggerMiddleware(req: Request, res: Response, next: NextFunction) {
console.log(`[${req.method}] ${req.url}`);
next();
}
5. Visualizando o Fluxo da API (Mermaid)
sequenceDiagram
participant Cliente
participant Express as Servidor Express (TS)
participant DTO as Validação DTO
participant DB as Banco de Dados
Cliente->>Express: POST /produtos (JSON)
Express->>DTO: Validar Tipos
DTO-->>Express: Dados OK
Express->>DB: Salvar Produto
DB-->>Express: Sucesso
Express-->>Cliente: 201 Created (JSON)
6. Exercícios Práticos 📝
- Básico: Configure um novo projeto Node.js com TypeScript e instale os tipos do Express.
- Básico: Crie uma rota
GETque retorne um objeto tipado com informações do servidor. - Intermediário: Crie uma interface
ProdutoDTOe use-a para tipar oreq.bodyde uma rota de criação. - Intermediário: Implemente um middleware que verifica se um
tokenestá presente no header da requisição. - Desafio: Crie uma mini API que gerencia uma lista em memória de "Tarefas" (Tasks). Use interfaces para as tarefas e garanta que as rotas de
POSTePUTusem DTOs.
🚀 Mini-Projeto da Aula
Desenvolva uma Mini API REST de Biblioteca.
- Rotas para listar, criar e buscar livros por ID.
- Use um array em memória para simular o banco de dados.
- Tipagem completa de Requests, Responses e Entidades.
- Implemente um tratamento de erros centralizado que use o tipo Error.
Próxima Aula: Vamos levar o TypeScript para o navegador com TypeScript com Frontend Moderno (React/Vue/Angular)!
Aula 11 – TypeScript com Frontend Moderno ⚛️
Objetivo
Nesta aula, aprenderemos como o TypeScript potencializa o desenvolvimento frontend, focando em React. Veremos como tipar componentes, props, hooks e o estado global da aplicação de forma profissional.
1. Por que TypeScript no Frontend? 🌐
Aplicações frontend lidam com muitas interações de usuário e dados dinâmicos. O TS ajuda a: - Garantir que as Props passadas para um componente estão corretas. - Evitar erros ao acessar o Estado (State). - Facilitar o uso de Context API e bibliotecas de gerenciamento de estado.
2. Componentes e Props Tipados 🧩
Em React com TS, definimos uma interface para as props do componente.
interface BotaoProps {
texto: string;
cor?: "primary" | "secondary";
onClick: () => void;
}
const Botao = ({ texto, cor = "primary", onClick }: BotaoProps) => {
return (
<button className={cor} onClick={onClick}>
{texto}
</button>
);
};
3. Hooks Tipados (useState / useRef) 🎣
O TS geralmente infere o tipo do useState, mas às vezes precisamos ser explícitos, especialmente com arrays ou objetos.
import { useState, useRef } from 'react';
// Inferência automática
const [contagem, setContagem] = useState(0);
// Explícito (Union Type)
const [usuario, setUsuario] = useState<Usuario | null>(null);
// Tipagem de Referências (DOM)
const inputRef = useRef<HTMLInputElement>(null);
4. Context API Tipada 🌍
Compartilhar estado global com segurança de tipos é um dos maiores benefícios do TS no React.
interface ThemeContextType {
tema: "light" | "dark";
toggleTema: () => void;
}
const ThemeContext = createContext<ThemeContextType | undefined>(undefined);
5. Visualizando a Hierarquia de Componentes (Mermaid)
graph TD;
App[App.tsx] --> Header[Header.tsx];
App --> Main[MainContent.tsx];
Main --> Card["Card.tsx (Generic)"];
Main --> List["List.tsx (Generic)"];
style Card fill:#f9f,stroke:#333
style List fill:#f9f,stroke:#333
6. Exercícios Práticos 📝
- Básico: Crie um componente
Saudacaoque receba uma propnome: stringe exiba na tela. - Básico: Crie um estado usando
useStatepara armazenar uma lista de strings e exiba-os em uma lista<ul>. - Intermediário: Crie um componente de
Inputreutilizável que aceite todas as props padrão de um input HTML (useReact.InputHTMLAttributes). - Intermediário: Implemente um hook customizado
useLocalStorage<T>que seja genérico. - Desafio: Crie um componente
Tabela<T>genérico que receba uma lista de dados de tipoTe uma configuração de colunas para renderizá-los.
🚀 Mini-Projeto da Aula
Desenvolva um Dashboard de Tarefas (Todo List).
- Componentes para: Header, AddTodoForm, TodoList e TodoItem.
- Interfaces bem definidas para a entidade Todo (id, titulo, concluida).
- Use useState para gerenciar a lista e garanta que todas as funções de manipulação (adicionar, remover, alternar status) estejam devidamente tipadas.
Próxima Aula: Vamos aprender a conectar nossas aplicações ao mundo externo em Integração com APIs e Tipagem de Dados Externos!
Aula 12 – Integração com APIs e Tipagem de Dados Externos 📡
Objetivo
Nesta aula, aprenderemos a consumir serviços externos garantindo a integridade dos dados. Veremos como tipar respostas do Axios/Fetch, usar o padrão DTO para transformar dados e introduziremos a validação em runtime com bibliotecas como o Zod.
1. Fetch e Axios com TypeScript 🌐
Ao fazer uma requisição, o TypeScript não sabe o que virá da rede. Precisamos informar o tipo esperado para ter segurança ao manipular a resposta.
Exemplo com Axios
import axios from 'axios';
interface Usuario {
id: number;
name: string;
email: string;
}
async function buscarUsuario(id: number): Promise<Usuario> {
const { data } = await axios.get<Usuario>(`https://api.exemplo.com/users/${id}`);
return data;
}
2. O Padrão DTO (Data Transfer Object) 🔄
Muitas vezes, a API retorna dados em um formato bruto que não queremos usar diretamente no nosso frontend ou lógica de negócio. O DTO serve para mapear esses dados.
interface UsuarioAPI {
id: number;
full_name: string;
user_email: string;
}
interface UsuarioApp {
id: number;
nome: string;
email: string;
}
function mapToApp(user: UsuarioAPI): UsuarioApp {
return {
id: user.id,
nome: user.full_name,
email: user.user_email
};
}
3. Validação em Runtime com Zod 🛡️
O TypeScript remove os tipos no build final. Para garantir que os dados externos são realmente o que dizem ser enquanto o app roda, usamos o Zod.
Criando um Schema
import { z } from 'zod';
const UsuarioSchema = z.object({
id: z.number(),
nome: z.string().min(3),
email: z.string().email()
});
type Usuario = z.infer<typeof UsuarioSchema>;
// Validação
const resultado = UsuarioSchema.safeParse(dadosExternos);
if (!resultado.success) {
console.error("Dados inválidos!", resultado.error);
}
4. Tratamento de Erros de API ⚠️
Devemos tipar os erros para dar um feedback útil ao usuário.
try {
const user = await buscarUsuario(1);
} catch (error) {
if (axios.isAxiosError(error)) {
console.error("Erro na API:", error.response?.data.message);
} else {
console.error("Erro inesperado:", error);
}
}
5. Visualizando o Ciclo de Dados (Mermaid)
graph LR;
API[API Externa] -- "JSON" --> Schema{Validação Zod};
Schema -- "Falha" --> Erro[Tratamento de Erros];
Schema -- "Sucesso" --> DTO[Mapeador DTO];
DTO --> App[Estado da Aplicação];
style Schema fill:#f96,stroke:#333
style DTO fill:#bbf,stroke:#333
6. Exercícios Práticos 📝
- Básico: Crie uma interface para a resposta da API JSONPlaceholder (objetos de
Post). - Básico: Use o
fetchpara buscar dados e exiba o título do primeiro post no console (tipado). - Intermediário: Crie uma função que receba um objeto de API "sujo" e retorne um objeto "limpo" usando o padrão DTO.
- Intermediário: Instale o Zod e crie um schema para um objeto
Produto. Tente validar um objeto que falte propriedades obrigatórias. - Desafio: Implemente uma função genérica
request<T>(url: string)que use Axios e retorne umaPromise<T>, tratando erros de rede automaticamente.
🚀 Mini-Projeto da Aula
Desenvolva um Buscador de Repositórios do GitHub.
- Use a API pública do GitHub (https://api.github.com/users/USUARIO/repos).
- Crie interfaces para o Repositorio.
- Valide os dados recebidos com Zod.
- Exiba a lista de repositórios (nome, descrição e estrelas) em uma interface React ou no console do Node de forma tipada.
Próxima Aula: Vamos garantir que nosso código continue funcionando com Testes com TypeScript!
Aula 13 – Testes com TypeScript 🧪
Objetivo
Nesta aula, aprenderemos a garantir a qualidade e a estabilidade do nosso código usando testes automatizados. Veremos como configurar o Jest com TypeScript, criar mocks tipados e escrever testes unitários e de integração robustos.
1. Configurando o Jest com TypeScript 🛠️
O Jest é o framework de testes mais popular no ecossistema JS/TS. Para rodar testes em TS, usamos o ts-jest.
Instalação
2. Testes Unitários Tipados 🧩
Testes unitários testam a menor parte possível do código (funções, classes) de forma isolada.
// math.ts
export const somar = (a: number, b: number) => a + b;
// math.test.ts
import { somar } from './math';
describe('Função somar', () => {
it('deve retornar 5 ao somar 2 e 3', () => {
const resultado: number = somar(2, 3);
expect(resultado).toBe(5);
});
});
3. Mocks Tipados com TypeScript 🎭
Mocks são usados para substituir dependências complexas (como APIs ou Banco de Dados) por versões controladas durante os testes.
import axios from 'axios';
import { buscarUsuario } from './servico';
jest.mock('axios');
const mockedAxios = axios as jest.Mocked<typeof axios>;
it('deve buscar um usuário com sucesso', async () => {
mockedAxios.get.mockResolvedValue({ data: { id: 1, nome: "Ricardo" } });
const user = await buscarUsuario(1);
expect(user.nome).toBe("Ricardo");
});
4. Testes de Integração 🔗
Testes de integração verificam se diferentes partes do sistema (como Rotas da API e Lógica de Negócio) funcionam bem juntas.
import request from 'supertest';
import app from './app';
describe('API de Usuários', () => {
it('deve criar um novo usuário', async () => {
const res = await request(app)
.post('/usuarios')
.send({ nome: 'Teste', email: 'teste@exemplo.com' });
expect(res.status).toBe(201);
expect(res.body.nome).toBe('Teste');
});
});
5. Visualizando o Ciclo de Testes (Mermaid)
graph TD;
Red["1. Falha (Vermelho)"] --> Green["2. Passa (Verde)"];
Green --> Refactor["3. Refatoração"];
Refactor --> Red;
style Red fill:#f99,stroke:#333
style Green fill:#9f9,stroke:#333
style Refactor fill:#99f,stroke:#333
6. Exercícios Práticos 📝
- Básico: Configure o Jest em um projeto TypeScript e crie um teste para uma função de multiplicão simples.
- Básico: Escreva um teste que verifique se uma função que lança erro realmente o faz (use
toThrow()). - Intermediário: Crie uma classe
Calculadorae escreva um conjunto de testes (describe) para todos os seus métodos. - Intermediário: Use o
jest.spyOn()para verificar se uma função foi chamada dentro de outra. - Desafio: Escreva um teste de integração para uma rota
GET /produtosque deve retornar uma lista de produtos tipados.
🚀 Mini-Projeto da Aula
Crie uma Suíte de Testes para o Repositório Genérico.
- Recupere o código do repositório da Aula 06.
- Escreva testes unitários para os métodos salvar, obterTodos e buscarPorId.
- Garanta 100% de cobertura nos métodos do repositório.
- Use mocks se o repositório depender de alguma função externa de persistência.
Próxima Aula: Vamos aprender a aplicar as melhores práticas de design com Padrões de Projeto com TypeScript!
Aula 14 – Padrões de Projeto com TypeScript 🛡️
Objetivo
Nesta aula, aprenderemos a elevar a qualidade do nosso software aplicando Padrões de Projeto (Design Patterns). Veremos como o TypeScript facilita a implementação de arquiteturas robustas usando Repositories, Services e Injeção de Dependência.
1. Padrão Repository e Service Layer 🏗️
A separação de responsabilidades é essencial. O Repository cuida do acesso aos dados, enquanto o Service cuida da lógica de negócio.
Estrutura
- Repository:
buscarTodos(),salvar(). - Service:
criarNovoUsuario(),validarRegrasDeNegocio().
interface IUsuarioRepository {
salvar(usuario: Usuario): Promise<void>;
}
class UsuarioService {
constructor(private repo: IUsuarioRepository) {}
async registrar(nome: string) {
// Lógica de negócio aqui
await this.repo.salvar({ nome });
}
}
2. Injeção de Dependência (DI) 💉
Em vez de criar as dependências dentro da classe, nós as "injetamos" (geralmente pelo construtor). Isso torna o código mais fácil de testar (usando mocks).
// No mundo real, usamos frameworks como Inversify ou Nestjs
const meuRepo = new SqlUsuarioRepository();
const meuServico = new UsuarioService(meuRepo);
3. Padrão Factory 🏭
Usado quando a criação de um objeto é complexa ou depende de condições.
class PagamentoFactory {
static criar(tipo: "cartao" | "boleto") {
if (tipo === "cartao") return new PagamentoCartao();
return new PagamentoBoleto();
}
}
4. Padrão Strategy ♟️
Permite definir uma família de algoritmos, colocá-los em classes separadas e tornar seus objetos intercambiáveis.
interface EstrategiaDesconto {
calcular(valor: number): number;
}
class DescontoBlackFriday implements EstrategiaDesconto {
calcular(valor: number) { return valor * 0.5; }
}
5. Visualizando o Padrão Repository (Mermaid)
graph LR;
Controller[Controller / API] --> Service[Service - Lógica];
Service --> RepoInterface[Interface do Repositório];
RepoInterface --> SqlRepo[SQL Repository];
RepoInterface --> MongoRepo[Mongo Repository];
style RepoInterface fill:#f9f,stroke:#333
6. Exercícios Práticos 📝
- Básico: Crie uma classe
LogServicee use injeção de dependência para passá-la para outra classe. - Básico: Implemente um
Factoryque crie diferentes tipos deNotificacao(Email, SMS). - Intermediário: Implemente o padrão
Strategypara diferentes formas de calcular o frete (Normal, Expresso). - Intermediário: Crie uma interface
IUserRepositorye implemente uma versãoInMemoryUserRepository. - Desafio: Refatore o Mini-Projeto da Aula 10 aplicando os padrões Repository e Service Layer.
🚀 Mini-Projeto da Aula
Implemente um Sistema de Processamento de Pagamentos. - Use o padrão Factory para criar o método de pagamento. - Use o padrão Strategy para aplicar diferentes taxas dependendo do método. - Use Injeção de Dependência para passar o serviço de log para o processador de pagamentos. - Tudo deve ser 100% tipado com interfaces.
Próxima Aula: Vamos aprender a escrever código limpo e entender a arquitetura em Clean Code e Arquitetura!
Aula 15 – Clean Code e Arquitetura 📐
Objetivo
Nesta aula, consolidaremos os conhecimentos técnicos com os princípios de código limpo e arquitetura. Aprenderemos a aplicar o SOLID, organizar o projeto em camadas e entenderemos os fundamentos do Domain-Driven Design (DDD).
1. Princípios SOLID com TypeScript 💎
O SOLID é um conjunto de cinco princípios que tornam o software mais compreensível, flexível e sustentável.
| Letra | Princípio | Descrição no TS |
|---|---|---|
| S | Single Responsibility | Uma classe/função deve ter apenas uma razão para mudar. |
| O | Open/Closed | Aberto para extensão, fechado para modificação. |
| L | Liskov Substitution | Subclasses devem ser substituíveis por suas classes base. |
| I | Interface Segregation | Muitas interfaces específicas são melhores que uma geral. |
| D | Dependency Inversion | Dependa de abstrações (interfaces), não de implementações. |
2. Separação de Responsabilidades e Camadas 🏢
Uma aplicação profissional é dividida em camadas para facilitar a manutenção e os testes.
- Domain: Onde vivem as regras de negócio e interfaces principais.
- Application: Casos de uso e lógica de orquestração (Services).
- Infrastructure: Detalhes técnicos (Base de dados, chamadas de API, Frameworks).
3. Domain-Driven Design (Introdução) 🗺️
O DDD foca em entender o problema do cliente e modelar o software fielmente a esse problema. - Entities: Objetos com identidade única (ex: Usuário com ID). - Value Objects: Objetos definidos por seus atributos (ex: Endereço). - Repositories: Porta de saída para persistência.
4. Boas Práticas Profissionais 🚀
- Nomes Significativos: Use nomes que revelem a intenção (
isValidem vez dev). - Funções Pequenas: Cada função deve fazer apenas uma coisa.
- Evite Comentários Óbvios: O código deve ser autoexplicativo através de tipos e bons nomes.
5. Visualizando a Arquitetura em Camadas (Mermaid)
graph TD;
External[Mundo Externo / UI / API] --> Infra[Infraestrutura];
Infra --> App[Aplicação / Services];
App --> Domain[Domínio / Entidades];
style Domain fill:#f9f,stroke:#333
6. Exercícios Práticos 📝
- Básico: Identifique uma violação do princípio de Responsabilidade Única em um código e proponha uma refatoração.
- Básico: Renomeie variáveis e funções de um código legado para nomes mais semânticos e tipados.
- Intermediário: Crie uma interface "Geral" e quebre-a em três interfaces menores (Segregação de Interface).
- Intermediário: Implemente um "Value Object" para representar um CPF, incluindo a validação no construtor.
- Desafio: Esboce a estrutura de pastas de um projeto seguindo a separação entre Domain, Application e Infrastructure.
🚀 Mini-Projeto da Aula
Refatore o seu projeto acumulado até aqui (Sistema de Pagamentos ou Biblioteca) aplicando os princípios de Clean Code e SOLID. - Garanta que nenhuma função tenha mais de 20 linhas. - Verifique se a camada de domínio é independente de bibliotecas externas (como o Express). - Utilize Injeção de Dependência para todos os serviços e repositórios.
Próxima Aula: É hora do Projeto Final e Deploy! Vamos colocar tudo em prática e lançar nossa aplicação!
Aula 16 – Projeto Final e Deploy 🚀
Objetivo
Chegamos ao fim da nossa jornada! Nesta aula, consolidaremos tudo o que aprendemos em um projeto completo. Veremos como preparar nosso código para produção, Dockerizar a aplicação e realizar o deploy em nuvem.
1. O Projeto Final: Sistema de E-commerce Full-Stack 🛒
O desafio final é construir uma API robusta e uma interface simples que se conectem.
Requisitos Técnicos
- Tipagem: 100% dos dados tipados (Interfaces, Types, Enums).
- Backend: Node.js + Express com Repository Pattern e Services.
- Frontend: React com Hooks e Context API tipados.
- Segurança: Validação de dados externos com Zod.
- Qualidade: Pelo menos 20% de cobertura de testes unitários com Jest.
2. Preparando o Build para Produção 🏗️
O código TypeScript não roda diretamente em servidores de produção. Precisamos transpilá-lo para JavaScript.
Atenção
Sempre verifique se a pasta dist/ está no seu .gitignore. Você deve subir o código fonte (src/), não o código compilado.
3. Dockerização (Opcional Profissional) 🐳
O Docker garante que sua aplicação rode da mesma forma em qualquer máquina.
# Dockerfile
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
CMD ["node", "dist/index.js"]
4. Estratégias de Deploy 🚀
Opções Populares:
- Vercel / Netlify: Excelentes para o Frontend (React).
- Railway / Render / Heroku: Ótimos para o Backend (Node.js).
- AWS / Google Cloud: Para projetos de grande escala.
5. Visualizando o Ciclo de Vida do Projeto (Mermaid)
graph TD;
Dev[Desenvolvimento TS] --> Test[Testes Automatizados];
Test --> Build[Build / Transpilação];
Build --> Artifact[Artefato JS];
Artifact --> Deploy[Deploy em Nuvem];
Deploy --> Monitor[Monitoramento e Feedbacks];
style Deploy fill:#f96,stroke:#333
6. Exercícios Práticos 📝
- Básico: Execute o comando
tsce veja o JavaScript gerado na pasta de saída. - Básico: Crie um arquivo
.gitignoreque ignore as pastasnode_modulesedist. - Intermediário: Configure um script no
package.jsonchamadostartque rode o código já compilado. - Intermediário: Crie um
Dockerfilebásico para sua aplicação Node.js. - Desafio: Realize o deploy de uma pequena API TypeScript em um serviço gratuito como o Render ou Railway.
🎓 Conclusão do Curso
Parabéns! Você completou o treinamento TypeScript Profissional. Você agora domina uma das linguagens mais requisitadas do mercado e está pronto para construir aplicações escaláveis, seguras e de alta qualidade.
Obrigado por participar! Continue praticando e explorando a documentação oficial em typescriptlang.org.
Exercicios
Listas de Exercícios 🏋️
Pratique o que aprendeu com listas graduadas (Fácil, Médio, Desafio) focadas em TypeScript Profissional.
-
Módulo 1: Core & Linguagem
-
Módulo 2: Ecossistema & Apps
Exercícios: Aula 01 – Introdução ao TypeScript e Setup Profissional 🧠
🟢 Nível: Básico
- Instalação Local: Inicialize um projeto Node.js (
npm init -y) e instale o TypeScript como dependência de desenvolvimento. - Configuração Inicial: Gere o arquivo
tsconfig.jsone altere a propriedadeoutDirpara "./dist" erootDirpara "./src".
🟡 Nível: Intermediário
- Compilação Manual: Crie um arquivo
src/app.ts, adicione umconsole.loge execute o comandonpx tscpara gerar o arquivo na pastadist. - Watch Mode: Configure o compilador para monitorar alterações automaticamente (
watch mode) e valide se o arquivo JS é atualizado ao salvar o TS.
🔴 Nível: Desafio
- Automação com NPM: No seu
package.json, crie dois scripts:build(para compilar uma única vez) edev(para rodar o compilador em modo watch). Teste ambos os comandos via terminal.
Exercícios: Aula 02 – Tipos Fundamentais e Inferência 🛠️
🟢 Nível: Básico
- Declaração de Primitivos: Crie variáveis para armazenar seu nome, sua idade e se você gosta de TypeScript (booleano), usando tipagem explícita.
- Arrays Simples: Crie um array de números contendo os anos em que você realizou cursos e um array de strings com os nomes desses cursos.
🟡 Nível: Intermediário
- Trabalhando com Tuplas: Crie uma tupla chamada
coordenadasque aceite dois números (latitude e longitude). - Uso de Enums: Crie um
enumchamadoNivelAcessocom as opçõesADMIN,USEReGUEST. Crie uma variável do tipo deste enum.
🔴 Nível: Desafio
- Segurança com Unknown: Crie uma função que aceita um parâmetro do tipo
unknown. Dentro dela, usetypeofpara verificar se é uma string; se for, imprima-a em letras maiúsculas; caso contrário, imprima uma mensagem genérica.
Exercícios: Aula 03 – Tipos Avançados 🧩
🟢 Nível: Básico
- Union Types: Crie uma variável que possa receber
stringouboolean. - Literal Types: Crie um tipo chamado
Alinhamentoque permita apenas os valores"left","center"ou"right".
🟡 Nível: Intermediário
- Intersection Types: Crie dois tipos de objetos,
Pessoa(com nome) eTrabalhador(com cargo), e crie um terceiro tipo que seja a interseção de ambos. - Narrowing com typeof: Escreva uma função que receba
number | stringe retorne o dobro se for número ou o comprimento se for string.
🔴 Nível: Desafio
- Validação Completa: Crie um Type Alias para um
UsuarioAPIque pode ter um ID numérico ou sernull. Use Type Guards para garantir que você só acesse propriedades do ID se ele não for nulo.
Exercícios: Aula 04 – Interfaces e Modelagem de Domínio 🏗️
🟢 Nível: Básico
- Interface Simples: Crie uma interface
Usuariocomnome,idadee uma propriedade opcionalsite. - Extensão: Crie uma interface
Adminque estendaUsuarioe adicione a propriedadenivel(número).
🟡 Nível: Intermediário
- Readonly: Crie uma interface
Configuracaoonde todas as propriedades sejamreadonly. Tente alterar uma após a criação. - Interface de Função: Defina uma interface para uma função que receba dois números e retorne um booleano.
🔴 Nível: Desafio
- Modelagem de Sistema: Modele as interfaces para um sistema de "Pedidos de Ecommerce". Deve haver um
Cliente, umProdutoe umPedido(que contém uma lista de produtos e o cliente).
Exercícios: Aula 05 – Classes e Programação Orientada a Objetos 🏛️
🟢 Nível: Básico
- Classe Simples: Crie uma classe
Animalcom um métodofalar(). - Herança: Crie uma classe
Cachorroque herda deAnimale sobrescreva o métodofalar()para latir.
🟡 Nível: Intermediário
- Modificadores de Acesso: Crie uma classe
Contacom um atributosaldoprivado. Adicione métodos para depositar e ver o saldo. - Getters e Setters: Crie uma classe
Retangulocomlarguraealtura. Use getters e setters para garantir que os valores sejam sempre positivos.
🔴 Nível: Desafio
- Abstração: Crie uma classe abstrata
Funcionariocom um método abstratocalcularSalario(). Implemente as subclassesDesenvolvedoreGerentecom lógicas de cálculo diferentes.
Exercícios: Aula 06 – Generics (Programação Genérica) 📦
🟢 Nível: Básico
- Função Generics: Escreva uma função genérica chamada
duplicar<T>que receba um item e retorne um array contendo o item duas vezes. - Array Genérico: Crie uma função que receba um array genérico e retorne o último elemento.
🟡 Nível: Intermediário
- Classe Genérica: Crie uma classe
Pilha<T>que permita adicionar (push) e remover (pop) itens de um tipo genérico. - Constraints: Crie uma função genérica que aceite apenas objetos que possuam a propriedade
.id.
🔴 Nível: Desafio
- Interface Genérica: Crie uma interface para uma
RespostaAPI<T>que contenha os camposstatus,data(do tipo T) eerror. Teste-a com diferentes tipos de dados.
Exercícios: Aula 07 – Utility Types e Manipulação de Tipos ⚙️
🟢 Nível: Básico
- Partial: Use o utilitário
Partialem uma interfaceUsuariopara criar uma variável que tenha apenas o nome. - Readonly: Crie uma versão
Readonlyde um objetoCarroe tente alterar uma propriedade.
🟡 Nível: Intermediário
- Pick e Omit: A partir de uma interface
Funcionario, usePickpara criar um tipo com apenasnomeecargo, eOmitpara criar um tipo que não tenha osalario. - Record: Use o
Recordpara mapear códigos de erro (números) para mensagens de erro (strings).
🔴 Nível: Desafio
- Mapeamento de API: Crie um tipo que represente a resposta de uma "atualização de perfil", onde todos os campos do usuário original são opcionais, exceto o
id, que deve ser obrigatório.
Exercícios: Aula 08 – Manipulação Avançada de Tipos 🧪
🟢 Nível: Básico
- keyof: Use o operador
keyofem uma interfaceCarropara criar uma união de suas chaves. - Indexed Access: Dada a interface
Config, obtenha o tipo da propriedadeversaousando acesso indexado.
🟡 Nível: Intermediário
- Conditional Types: Crie um tipo que verifique se um dado tipo
Té uma string. Se for, retorne"TEXTO", se não, retorne"OUTRO". - Template Literals: Crie um tipo que combine as direções
"Norte" | "Sul"com as intensidades"Forte" | "Fraca".
🔴 Nível: Desafio
- Uso de infer: Escreva um tipo utilitário que extraia o tipo do primeiro elemento de uma tupla genérica usando
infer.
Exercícios: Aula 09 – Módulos e Organização Profissional 📁
🟢 Nível: Básico
- Export/Import: Crie um módulo para uma classe
Calculadorae importe-o em outro arquivo para realizar uma soma. - Export Default: Exporte uma constante por padrão e importe-a com um apelido à sua escolha.
🟡 Nível: Intermediário
- Barrel Files: Crie uma estrutura de pastas para
controllerse crie um arquivoindex.tsque exporta tudo o que há dentro dela. - Namespaces: Crie um
namespacepara agrupar funções de validação de formulário (e-mail, senha).
🔴 Nível: Desafio
- Path Aliases: Configure um alias
@modelsnotsconfig.jsone use-o para importar uma interface de uma pasta profunda do projeto.
Exercícios: Aula 10 – TypeScript com Node.js (Backend) 🟢
🟢 Nível: Básico
- Instalação Backend: Inicialize um projeto Node, instale o
expresse os tipos@types/express. - Primeira Rota: Crie uma rota
GET /que retorne uma mensagem de boas-vindas tipada.
🟡 Nível: Intermediário
- Tipagem de Body: Crie uma rota
POST /usuariose use uma interface para tipar os dados recebidos noreq.body. - Middleware de Log: Implemente um middleware que registre o método e a URL de cada requisição.
🔴 Nível: Desafio
- Tratamento de Erros: Crie um middleware de erro customizado que capture exceções e retorne uma resposta JSON padronizada e tipada.
Exercícios: Aula 11 – TypeScript com Frontend Moderno ⚛️
🟢 Nível: Básico
- Props de Componente: Crie um componente
Botaoem React que receba as propslabel(string) eativo(boolean). - Estado Simples: Use o
useStatepara criar um contador tipado que só aceite números.
🟡 Nível: Intermediário
- Eventos: Tipar o evento de um formulário (
React.FormEvent) em uma funçãohandleSubmit. - useRef Tipado: Crie um formulário onde um botão "Focar" use um
useRefpara dar foco a um input de texto.
🔴 Nível: Desafio
- Context API: Crie um contexto para gerenciar as informações do usuário logado. Defina uma interface para o contexto e garanta que o provedor seja tipado corretamente.
Exercícios: Aula 12 – Integração com APIs e Tipagem de Dados Externos 📡
🟢 Nível: Básico
- Interface de API: Crie uma interface para o objeto retornado por uma API de clima (ex: OpenWeather).
- Fetch Tipado: Realize um
fetchpara uma URL de teste e use o operadoraspara converter o resultado para a sua interface.
🟡 Nível: Intermediário
- Axios Generics: Use o Axios para fazer um
getgenérico chamando uma interfacePost. - Mapeamento DTO: Crie uma função que transforme um objeto de usuário da API (com nomes em snake_case) para um objeto da aplicação (com nomes em camelCase).
🔴 Nível: Desafio
- Zod Schema: Crie um schema Zod para validar a entrada de um formulário de login (email e senha com requisitos de tamanho).
Exercícios: Aula 13 – Testes com TypeScript 🧪
🟢 Nível: Básico
- Setup Jest: Configure um arquivo
jest.config.jsbásico para aceitar arquivos TypeScript. - Primeiro Teste: Crie uma função que retorne a soma de três números e escreva um teste que valide o resultado.
🟡 Nível: Intermediário
- Teste de Exceção: Escreva uma função que valide a idade de um usuário e lance um erro se for menor de 18. Teste se o erro é lançado corretamente.
- Mock de Função: Use
jest.fn()para simular o comportamento de um callback passado para uma função de processamento.
🔴 Nível: Desafio
- Mock de API: Use o
jest.mock('axios')para simular uma chamada de API e validar se o seu serviço está tratando a resposta corretamente.
Exercícios: Aula 14 – Padrões de Projeto com TypeScript 🛡️
🟢 Nível: Básico
- Injeção de Dependência: Crie uma função que receba um objeto de configuração por parâmetro (em vez de usá-lo globalmente).
- Singleton: Implemente o padrão Singleton para uma classe de Gerenciamento de Configurações.
🟡 Nível: Intermediário
- Repository Pattern: Crie uma interface
IRepository<T>e implemente uma versão básica para uma entidadeProduto. - Factory Pattern: Implemente uma fábrica de objetos que crie diferentes tipos de "Veículos".
🔴 Nível: Desafio
- Strategy Pattern: Use o padrão Strategy para implementar diferentes formas de cálculo de imposto baseadas no tipo de produto.
Exercícios: Aula 15 – Clean Code e Arquitetura 📐
🟢 Nível: Básico
- Nomes Semânticos: Refatore uma função com nomes genéricos (ex:
a,b,fn1) para nomes que expliquem sua função. - Função de Responsabilidade Única: Quebre uma função que faz duas coisas (ex: valida e salva no banco) em duas funções separadas.
🟡 Nível: Intermediário
- Inversão de Dependência: Refatore uma classe que instancia diretamente um serviço para que ela receba o serviço no construtor.
- Segregação de Interface: Quebre uma interface "gorda" que tem 10 métodos em três interfaces menores e mais específicas.
🔴 Nível: Desafio
- Domain Entities: Crie uma Entidade de Domínio para um "Pedido" que contenha uma lógica interna para calcular o total sem depender de serviços externos.
Exercícios: Aula 16 – Projeto Final e Deploy 🚀
🟢 Nível: Básico
- Build de Produção: Execute o comando
npm run builde analise o código gerado na pastadist. - Scripts NPM: Configure um script
startque execute o arquivodist/index.js.
🟡 Nível: Intermediário
- Docker Básico: Escreva um
Dockerfileque copie apenas o necessário para rodar a aplicação já compilada. - Variáveis de Ambiente: Configure o seu projeto para ler a porta do servidor de uma variável de ambiente (
process.env.PORT).
🔴 Nível: Desafio
- Pipeline CI/CD: Documente os passos necessários para configurar o deploy automático do seu projeto no GitHub Pages ou Vercel.
Projetos
Projetos Práticos 🚀
Construa portfólio com 16 mini-projetos reais e marcos importantes na sua trajetória.
-
Módulo 1: Core & Linguagem
-
Módulo 2: Ecossistema & Apps
Mini-Projeto: Aula 01 – Setup do Workspace Profissional 🛠️
Objetivo
Configurar um ambiente de desenvolvimento TypeScript completo, pronto para produção, seguindo as melhores práticas de organização de pastas e automação de scripts.
🏗️ Requisitos do Projeto
- Inicializar um projeto Node.js.
- Configurar o TypeScript com
tsconfig.json. - Organizar a estrutura de pastas (
srcedist). - Automatizar o processo de build e execução.
🛠️ Passo a Passo
1. Inicialização
Abra o terminal na pasta do projeto e execute:
2. Configuração do TS
Gere o arquivo de configuração e ajuste as seguintes propriedades:
Configurações recomendadas no tsconfig.json:
{
"compilerOptions": {
"target": "ES2020",
"module": "NodeNext",
"rootDir": "./src",
"outDir": "./dist",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
}
}
3. Scripts de Automação
No arquivo package.json, adicione:
"scripts": {
"dev": "ts-node-dev --respawn --transpile-only src/index.ts",
"build": "tsc",
"start": "node dist/index.js"
}
4. Código de Teste
Crie a pasta src/ e o arquivo index.ts:
✅ Verificação Final
- Execute
npm run deve verifique se o log aparece no terminal. - Altere o texto da mensagem e veja se o servidor reinicia sozinho.
- Execute
npm run builde verifique se a pastadist/foi criada com o arquivo.js.
Mini-Projeto: Aula 02 – Calculadora de IMC (Tipos Primitivos) ⚖️
Objetivo
Praticar o uso de tipos primitivos (number, string), inferência de tipos e interação simples via console.
🏗️ Requisitos do Projeto
- Receber peso e altura do usuário.
- Calcular o IMC (Peso / Altura²).
- Exibir o resultado formatado com uma classificação.
- Usar tipagem explícita para as variáveis principais.
🛠️ Passo a Passo
1. Estrutura do Código
No seu arquivo src/index.ts, defina as variáveis:
const nome: string = "Ricardo";
const peso: number = 85;
const altura: number = 1.80;
function calcularIMC(p: number, a: number): number {
return p / (a * a);
}
2. Lógica de Classificação
Use o resultado para determinar a categoria:
const imc = calcularIMC(peso, altura);
let classificacao: string;
if (imc < 18.5) classificacao = "Abaixo do peso";
else if (imc < 25) classificacao = "Peso normal";
else classificacao = "Sobrepeso";
console.log(`${nome}, seu IMC é ${imc.toFixed(2)} (${classificacao})`);
✅ Desafio Extra
- Use um
enumpara as categorias de classificação (ABAIXO, NORMAL, SOBREPESO). - Crie uma tupla para armazenar os dados do usuário:
[string, number, number].
Mini-Projeto: Aula 03 – Gerenciador de Inventário (Tipos Avançados) 📦
Objetivo
Utilizar Union Types, Type Aliases e Intersection Types para modelar um sistema de inventário de produtos.
🏗️ Requisitos do Projeto
- Definir tipos para diferentes categorias de produtos (Eletrônicos, Alimentos).
- Usar intersecção para criar modelos completos.
- Implementar uma função que aceita diferentes tipos de IDs (número ou string).
🛠️ Passo a Passo
1. Modelagem com Type Aliases
type Categoria = "Eletronico" | "Alimento" | "Vestuario";
type ProdutoBase = {
id: string | number;
nome: string;
preco: number;
categoria: Categoria;
};
type Especificacoes = {
peso: number;
dimensoes?: string;
};
// Intersection Type
type ProdutoCompleto = ProdutoBase & Especificacoes;
2. Manipulação Tipada
Crie um array de produtos e uma função para buscar por ID.
const inventario: ProdutoCompleto[] = [
{ id: 1, nome: "Celular", preco: 2000, categoria: "Eletronico", peso: 0.2 },
{ id: "A-123", nome: "Maçã", preco: 5, categoria: "Alimento", peso: 0.1 }
];
function buscar(id: string | number) {
return inventario.find(p => p.id === id);
}
✅ Desafio Extra
- Implemente um
Type Guardpara verificar se um produto é da categoria "Eletronico". - Use
Literal Typespara definir o status do produto:"em_estoque" | "esgotado".
Mini-Projeto: Aula 04 – Sistema de Gerenciamento de Tarefas (Interfaces) ✅
Objetivo
Modelar um sistema de tarefas (To-Do) corporativo usando interfaces, propriedades opcionais e herança de interfaces.
🏗️ Requisitos do Projeto
- Interface para
Usuario. - Interface para
Tarefacom campos opcionais. - Interface para
Projetoque agrupa várias tarefas. - Garantir imutabilidade em campos críticos com
readonly.
🛠️ Passo a Passo
1. Definição das Interfaces
interface IUser {
readonly id: number;
nome: string;
email: string;
}
interface ITask {
titulo: string;
descricao?: string;
concluida: boolean;
responsavel: IUser;
}
interface IProject {
nome: string;
tarefas: ITask[];
}
2. Implementação
Crie uma função que receba um IProject e retorne apenas as tarefas concluídas.
const meuProjeto: IProject = {
nome: "Refatoração TS",
tarefas: [
{ titulo: "Setup", concluida: true, responsavel: { id: 1, nome: "R", email: "r@b.com" } },
{ titulo: "Build", concluida: false, responsavel: { id: 1, nome: "R", email: "r@b.com" } }
]
};
function listarConcluidas(projeto: IProject): ITask[] {
return projeto.tarefas.filter(t => t.concluida);
}
✅ Desafio Extra
- Crie uma interface
ITaskUrgenteque estendeITaske adiciona um campoprazo: Date. - Use
Declaration Mergingpara adicionar uma propriedadeavatarna interfaceIUser.
Mini-Projeto: Aula 05 – Sistema Bancário (Classes e POO) 🏦
Objetivo
Aplicar os conceitos de Programação Orientada a Objetos (Classes, Modificadores de Acesso, Herança) para criar um sistema de gerenciamento de contas bancárias.
🏗️ Requisitos do Projeto
- Classe base
Contacom atributos privados. - Uso de
protectedpara permitir herança. - Subclasses
ContaCorrenteeContaPoupancacom regras específicas. - Implementação de getters e setters para validação de saldo.
🛠️ Passo a Passo
1. Classe Base
abstract class Conta {
constructor(
private _titular: string,
protected _saldo: number = 0
) {}
get saldo() { return this._saldo; }
depositar(valor: number): void {
if (valor > 0) this._saldo += valor;
}
abstract sacar(valor: number): boolean;
}
2. Extensões
class ContaCorrente extends Conta {
sacar(valor: number): boolean {
if (valor <= this._saldo + 100) { // Limite extra
this._saldo -= valor;
return true;
}
return false;
}
}
class ContaPoupanca extends Conta {
sacar(valor: number): boolean {
if (valor <= this._saldo) {
this._saldo -= valor;
return true;
}
return false;
}
}
✅ Desafio Extra
- Crie uma classe
Bancoque armazena um array deContae possui um método para listar todos os titulares e seus saldos (Polimorfismo). - Adicione uma propriedade
readonlychamadanumeroContagerada automaticamente no construtor.
Mini-Projeto: Aula 06 – Repositório de Dados Genérico (Generics) 📦
Objetivo
Criar uma estrutura de dados genérica e reutilizável que possa gerenciar qualquer tipo de entidade (Usuários, Produtos, etc.) mantendo a tipagem original.
🏗️ Requisitos do Projeto
- Classe genérica
Repository<T>. - Restrição (
Constraints) para garantir que as entidades possuam umid. - Métodos para Adicionar, Listar, Buscar por ID e Remover.
🛠️ Passo a Passo
1. Interface de Entidade
2. Classe Repositório
class Repository<T extends Entity> {
private data: T[] = [];
add(item: T): void {
this.data.push(item);
}
getAll(): T[] {
return this.data;
}
findById(id: number | string): T | undefined {
return this.data.find(item => item.id === id);
}
remove(id: number | string): void {
this.data = this.data.filter(item => item.id !== id);
}
}
✅ Desafio Extra
- Crie uma interface
Usere umaProducte instancie repositórios específicos para cada uma:const userRepo = new Repository<User>(). - Implemente um método
update(id, item)que atualize os dados de uma entidade sem mudar seuid.
Mini-Projeto: Aula 07 – Formulário de Perfil (Utility Types) ⚙️
Objetivo
Utilizar utilitários como Partial, Readonly, Pick e Omit para gerenciar diferentes estados de um perfil de usuário em uma aplicação.
🏗️ Requisitos do Projeto
- Interface completa de
UserProfile. - Criar um tipo para "Visualização Pública" (omitindo dados sensíveis).
- Criar um tipo para "Atualização de Perfil" (permitindo campos parciais).
- Garantir que o ID do usuário seja imutável.
🛠️ Passo a Passo
1. Modelo Base
interface UserProfile {
id: number;
nome: string;
email: string;
telefone?: string;
senhaHash: string;
dataCriacao: Date;
}
2. Uso de Utility Types
// Apenas o que o usuário pode ver de outros
type PublicProfile = Omit<UserProfile, "senhaHash" | "email">;
// O que enviamos para o banco ao atualizar (ID obrigatório, resto parcial)
type UpdatePayload = Partial<Omit<UserProfile, "id" | "dataCriacao">> & { id: number };
// Usuário imutável após carregado
type SecureUser = Readonly<UserProfile>;
✅ Desafio Extra
- Use
Pickpara criar um tipoUserContactque contenha apenasnomeeemail. - Use
Recordpara criar um objeto que mapeieiddo usuário para seuPublicProfile.
Mini-Projeto: Aula 08 – Dinamismo com Tipos (Advanced Manipulation) 🧪
Objetivo
Explorar propriedades dinâmicas usando keyof, Mapped Types e Template Literals para criar um sistema de notificações inteligente.
🏗️ Requisitos do Projeto
- Usar
keyofpara criar um sistema de acesso seguro a chaves. - Template Literals para gerar nomes de manipuladores de eventos.
- Criar tipos que se adaptam dinamicamente a modelos de dados.
🛠️ Passo a Passo
1. Acesso Dinâmico Seguro
function getProp<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
const config = { porta: 3000, host: "localhost" };
const p = getProp(config, "porta"); // OK e Tipado!
2. Sistema de Eventos Literais
type Eventos = "focus" | "blur" | "click";
type EventHandlers = {
[K in Eventos as `on${Capitalize<K>}`]: () => void;
};
const handlers: EventHandlers = {
onFocus: () => console.log("Focado"),
onBlur: () => {},
onClick: () => {}
};
✅ Desafio Extra
- Crie um
Mapped Typeque transforme todas as propriedades de um objeto em funções que retornam aquele tipo (Getters). - Use
Conditional Typespara criar um utilitário que remova a propriedade "id" de qualquer tipo de objeto passado.
Mini-Projeto: Aula 09 – Biblioteca Modular (Organização de Projeto) 📁
Objetivo
Organizar um sistema de gerenciamento de livros em uma estrutura modular profissional, utilizando ES Modules, Barrel Files e Path Aliases.
🏗️ Requisitos do Projeto
- Dividir o código em pastas:
models,serviceseapp. - Usar
index.tspara centralizar as exportações de cada pasta. - Configurar e usar um path alias
@corepara o diretório de modelos.
🛠️ Passo a Passo
1. Estrutura de Pastas
Crie a seguinte hierarquia:
src/
├── models/
│ ├── Livro.ts
│ └── index.ts
├── services/
│ ├── Biblioteca.ts
│ └── index.ts
└── index.ts
2. Barrel File em models
No arquivo src/models/index.ts:
3. Configurando o Alias no tsconfig.json
✅ Verificação Final
- Importe o modelo
LivroemBiblioteca.tsusando o alias:import { Livro } from '@core';. - Certifique-se de que o arquivo principal (
src/index.ts) importa apenas do serviço e executa uma lógica de teste (ex: adicionar um livro e listar).
Mini-Projeto: Aula 10 – API de Tarefas (Backend com Node.js) 🟢
Objetivo
Construir uma API REST funcional para gerenciamento de tarefas utilizando Node.js, Express e TypeScript, focando na tipagem de Request/Response e uso de DTOs.
🏗️ Requisitos do Projeto
- Criar rotas para: Listar, Criar e Deletar tarefas.
- Tipar rigorosamente o corpo da requisição (
JSON Body). - Implementar um middleware simples de log.
- Usar uma estrutura de "Base de Dados" em memória (Array tipado).
🛠️ Passo a Passo
1. Servidor Básico
import express, { Request, Response } from 'express';
const app = express();
app.use(express.json());
interface Tarefa {
id: number;
titulo: string;
feita: boolean;
}
const db: Tarefa[] = [];
2. Rotas Tipadas
app.get('/tarefas', (req: Request, res: Response) => {
res.json(db);
});
app.post('/tarefas', (req: Request<{}, {}, Omit<Tarefa, 'id'>>, res: Response) => {
const nova: Tarefa = { id: Date.now(), ...req.body };
db.push(nova);
res.status(201).json(nova);
});
✅ Desafio Extra
- Crie um middleware que verifique se o campo
tituloestá presente no corpo da requisição antes de passar para a rota de criação. - Implemente a rota
DELETE /tarefas/:idtratando o parâmetroidde forma tipada.
Mini-Projeto: Aula 11 – Dashboard de Usuários (Frontend React) ⚛️
Objetivo
Desenvolver uma interface simples em React com TypeScript para listar e adicionar usuários, focando na tipagem de Props, Hooks e Eventos.
🏗️ Requisitos do Projeto
- Componente
UserCardtipado. - Formulário para adicionar novos usuários.
- Uso de
useStatecom interface genérica. - Tipagem de eventos de clique e mudança de input.
🛠️ Passo a Passo
1. Definição da Interface
2. Componente de Lista
const UserList = () => {
const [users, setUsers] = useState<User[]>([]);
const addUser = (nome: string) => {
const newUser = { id: Date.now(), nome, cargo: "Dev" };
setUsers([...users, newUser]);
};
return (
<div>
{users.map(u => <UserCard key={u.id} user={u} />)}
<Form onAdd={addUser} />
</div>
);
};
✅ Desafio Extra
- Crie um
Context APIpara gerenciar o tema da aplicação (Light/Dark) e garanta que o provedor e o hookuseThemeestejam 100% tipados. - Tipar o evento do formulário para evitar o recarregamento da página (
e.preventDefault()).
Mini-Projeto: Aula 12 – Buscador de Repositórios (Integração API) 📡
Objetivo
Consumir a API pública do GitHub para buscar repositórios de um usuário, aplicando tipagem de dados externos, tratamento de erros e validação com Zod.
🏗️ Requisitos do Projeto
- Usar
Axiospara realizar as chamadas HTTP. - Definir interfaces para a resposta do GitHub.
- Validar os dados recebidos com um schema
Zod. - Implementar tratamento de erro para usuários não encontrados.
🛠️ Passo a Passo
1. Schema de Validação (Zod)
import { z } from 'zod';
const RepoSchema = z.object({
name: z.string(),
description: z.string().nullable(),
stargazers_count: z.number(),
html_url: z.string().url()
});
type Repo = z.infer<typeof RepoSchema>;
2. Chamada de API com Axios
async function getRepos(user: string): Promise<Repo[]> {
const { data } = await axios.get<Repo[]>(`https://api.github.com/users/${user}/repos`);
// Validar cada repositório da lista
return data.map(r => RepoSchema.parse(r));
}
✅ Desafio Extra
- Crie uma função "Mapper" que transforme as chaves vindas do GitHub (ex:
stargazers_count) para nomes mais amigáveis no seu código (ex:estrelas). - Exiba uma mensagem de erro customizada caso a API retorne um erro 404 (Usuário não encontrado).
Mini-Projeto: Aula 13 – Testando um Carrinho de Compras (Testes) 🧪
Objetivo
Implementar uma suíte de testes unitários para um sistema de carrinho de compras, utilizando Jest e TypeScript para garantir que cálculos de totais e descontos estejam corretos.
🏗️ Requisitos do Projeto
- Classe
Carrinhocom métodos:adicionar,removerecalcularTotal. - Testar se o carrinho inicia vazio.
- Testar se o total é calculado corretamente após adições.
- Mockar um "Serviço de Frete" para testar o total com entrega.
🛠️ Passo a Passo
1. Classe a ser Testada
export class Carrinho {
private itens: { nome: string, preco: number }[] = [];
adicionar(item: { nome: string, preco: number }) {
this.itens.push(item);
}
getTotal(): number {
return this.itens.reduce((acc, curr) => acc + curr.preco, 0);
}
}
2. Arquivo de Teste (.spec.ts)
import { Carrinho } from './Carrinho';
describe('Carrinho de Compras', () => {
it('deve calcular o total corretamente', () => {
const c = new Carrinho();
c.adicionar({ nome: 'Livro', preco: 50 });
c.adicionar({ nome: 'Mouse', preco: 100 });
expect(c.getTotal()).toBe(150);
});
});
✅ Desafio Extra
- Implemente um teste para verificar se o método
remover(nome)funciona conforme o esperado. - Adicione um teste que valide uma mensagem de erro caso tentemos adicionar um item com preço negativo.
- Configure o Jest para exibir o relatório de cobertura (
coverage) ao rodar os testes.
Mini-Projeto: Aula 14 – Gateway de Pagamentos (Design Patterns) 🛡️
Objetivo
Aplicar o padrão Strategy e Repository para criar um sistema de processamento de pagamentos flexível (Cartão, Boleto, Pix) sem acoplamento.
🏗️ Requisitos do Projeto
- Interface
IPaymentStrategy. - Implementações para
CreditCardPaymentePixPayment. - Classe
PaymentContextque executa a estratégia selecionada. - Uso de
Dependency Injectionpara passar a estratégia desejada.
🛠️ Passo a Passo
1. O Padrão Strategy
interface IPaymentStrategy {
process(amount: number): string;
}
class PixPayment implements IPaymentStrategy {
process(amount: number) { return `Pix de R$${amount} gerado.`; }
}
class CardPayment implements IPaymentStrategy {
process(amount: number) { return `Cartão de R$${amount} processado.`; }
}
2. O Contexto
class Checkout {
constructor(private strategy: IPaymentStrategy) {}
finalizar(valor: number) {
console.log(this.strategy.process(valor));
}
}
const pedido = new Checkout(new PixPayment());
pedido.finalizar(200);
✅ Desafio Extra
- Implemente o padrão
Factorypara instanciar a estratégia correta baseada em uma string (ex: "PIX", "CARD"). - Crie um
Repository(interface + implementação em memória) para salvar o histórico de pagamentos realizados.
Mini-Projeto: Aula 15 – Refatorando para Clean Code (Arquitetura) 📐
Objetivo
Transformar um código funcional, porém "sujo" (com funções gigantes e múltiplas responsabilidades), em um sistema seguindo os princípios SOLID e Clean Code.
🏗️ Requisitos do Projeto
- Dividir uma função "faz-tudo" em funções menores e específicas.
- Aplicar nomes significativos em variáveis e tipos.
- Isolar a lógica de negócio de efeitos colaterais (log, persistência).
- Garantir que cada classe tenha apenas uma responsabilidade (SRP).
🛠️ Passo a Passo
1. O Código Sujo (Antes)
Analise este código que calcula desconto, salva no banco e envia email de uma vez:
async function processar(pedido: any) {
let total = 0;
for(let i of pedido) { total += i.preco; }
if (total > 100) total *= 0.9;
await db.save(pedido, total);
await email.send("Pedido feito");
}
2. O Código Limpo (Depois)
Separe em classes e métodos:
- OrderScanner: Para somar os itens.
- DiscountService: Para aplicar regras de negócio.
- NotificationService: Para envio de avisos.
✅ Desafio Extra
- Aplique o Princípio da Inversão de Dependência (D do SOLID) no
NotificationService, permitindo trocarEmailporWhatsAppatravés de uma interface comum. - Implemente validações robustas que lancem exceções customizadas em vez de apenas retornar
null.
Projeto Final: Aula 16 – Aplicação Fullstack e Deploy 🚀
Objetivo
O desafio final! Integrar todos os conhecimentos do curso para criar uma aplicação completa (Node + React + TS), containerizar com Docker e preparar para o Deploy.
🏗️ Requisitos do Projeto
- Backend: API de catálogo de produtos com Node e Express.
- Frontend: Dashboard para visualização e compra via React.
- Integração: Consumo da API própria usando Axios e Zod.
- Docker: Criar um
Dockerfilefuncional. - Build: Scripts de build para produção ativos.
🛠️ Etapas de Execução
1. Desenvolvimento Integrado
- Aplique Interfaces e Shared Types entre os projetos.
- Utilize Design Patterns (Repository/Service) no Backend.
- Garanta Testes Unitários no núcleo da aplicação.
2. Preparação para Produção
No package.json:
3. Containerização (Docker)
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["npm", "start"]
✅ Critérios de Sucesso
- [ ] A aplicação roda localmente via
npm run dev. - [ ] O build de produção é gerado sem erros de tipagem.
- [ ] A imagem Docker é construída com sucesso.
- [ ] Existe uma documentação (
README.md) explicando como rodar o projeto.
🚀 Rumo ao Deploy!
Parabéns por chegar até aqui. Sua aplicação está pronta para o mundo real!
Quizzes
Quizzes Interativos 🧠
Avalie sua retenção de conhecimento após cada aula do curso TypeScript Profissional.
-
Módulo 1: Core & Linguagem
-
Módulo 2: Ecossistema & Apps
Quiz 01 - Introdução
Quiz 02 - Introdução
Quiz 03 - Introdução
Quiz 04 - Introdução
Quiz 05 - Introdução
Quiz 06 - Introdução
Quiz 07 - Introdução
Quiz 08 - Introdução
Quiz 09 - Introdução
Quiz 10 - Introdução
Quiz 11 - Introdução
Quiz 12 - Introdução
Quiz 13 - Introdução
Quiz 14 - Introdução
Quiz 15 - Introdução
Quiz 16 - Introdução
Slides
Slides de Apoio 📽️
Material visual utilizado durante as aulas teóricas do curso.
-
Módulo 1: Core & Linguagem
-
Módulo 2: Ecossistema & Apps
Aula 01 - Introdução ao TypeScript e Setup Profissional 🧠
Bem-vindos ao Curso! 🚀
"TypeScript Profissional"
O que vamos ver hoje? 📋
- Evolução do JavaScript
- Problemas da tipagem dinâmica
- O que é TypeScript?
- Setup do Ambiente Real
- Compilação e Watch Mode
O Problema: JavaScript Puro 🌪️
- Tipagem Dinâmica: Liberdade vs. Caos
- Erros que só aparecem em Proteção
Cannot read property 'x' of undefined- Falta de autocompletar e confiança
A Solução: TypeScript 🛡️
- Criado pela Microsoft
- Adiciona Tipagem Estática
- É um Superset do JavaScript
- Detecta erros antes de rodar o código
O Conceito de Superset 🧱
graph LR;
JS[JavaScript Moderno] --> TS[TypeScript];
note[Todo JS é um TS válido]
Estático vs Dinâmico ⚖️
- JS: Tipos são checados no Navegador (Runtime)
- TS: Tipos são checados no Editor/Compilador (Compile-time)
Benefícios Reais 💎
- Documentação Viva: O código diz o que ele faz
- Refatoração Segura: Mude o nome de algo e o TS avisa onde quebrou
- Produtividade: Autocompletar inteligente (IntelliSense)
Setup do Ambiente 🛠️
- Precisamos do Node.js instalado
- Gerenciador de pacotes: NPM ou Yarn
Instalando o Compilador 📥
Criando seu Primeiro Projeto 📂
O arquivo tsconfig.json ⚙️
- O cérebro do compilador
- Define como o código será transformado
- Ativa ou desativa regras de segurança
Propriedades Essenciais: target 🎯
- Define a versão do JavaScript gerada
es5,es6,esnext...
Propriedades Essenciais: rootDir e outDir 🏗️
- rootDir: Onde fica o seu código TS (
src) - outDir: Onde o JS compilado vai parar (
dist)
O Modo Estrito (strict) 🚨
truepor padrão (Recomendado!)- Impede o uso de
anyimplícito - Garante checagem de
nulleundefined
Escrevendo Código ✍️
Compilando o Código 🏗️
Verificando o Resultado 🔍
- O arquivo
.jsgerado não possui tipos - É JavaScript puro pronto para o navegador ou Node
Watch Mode: Agilidade ⚡
- Não precisa rodar
tsctoda hora
Ferramenta Bônus: ts-node 🏎️
- Roda o código TS direto no terminal sem gerar arquivos
- Ótimo para testes rápidos
Resumo da Aula 🏁
- TS = JS + Tipos
- Setup: Node + TSC
- Configuração: tsconfig.json
Próxima Aula: Tipos Fundamentais!
Vamos dominar a base da linguagem. 🚀
Perguntas? ❓
Aula 02 - Tipos Fundamentais e Inferência 🛠️
Recapitulando 🔄
- TypeScript adiciona tipos ao JavaScript
- O compilador protege nosso código
tsconfig.jsoné a base
Tipos Primitivos 🧱
Os blocos básicos: - string: textos - number: números (inteiros e decimais) - boolean: verdadeiro ou falso
Exemplo: Sintaxe de Anotação ✍️
O Poder da Inferência 🧠
- O TypeScript é inteligente!
- Se você atribui um valor, ele adivinha o tipo.
Quando Anotar? ⚖️
- Inferencia: Variáveis locais simples.
- Anotação: Parâmetros de função, retorno de funções e objetos complexos.
Trabalhando com Arrays 📚
Duas formas de escrever:
Arrays Fortemente Tipados 🛡️
- O TS impede que você adicione um
stringem um array denumber. - Segurança total em iterações (map, filter).
Tuplas: Arrays com Regras 📏
- Tamanho fixo e tipos específicos por posição.
Tuplas na Prática 📦
- Ideal para coordenadas (lat, long), retornos simples de funções ou estados (como no React).
Enums: Legibilidade 🏷️
- Define um conjunto de nomes para valores constantes.
Enums de String 🔠
- Valores mais claros para depuração.
O Tipo any (Perigo!) ⚠️
- Desativa a checagem de tipos.
- Use apenas em migrações ou casos extremos.
O Tipo unknown (Segurança) 🛡️
- Diferente do
any, ele não permite operações sem checagem de tipo prévia.
Estreitamento (Type Guards) 🔍
- Como "provar" ao TS o tipo de uma variável.
Void: Sem Retorno 🚫
- Usado em funções que executam uma tarefa mas não devolvem valor.
Never: O Impossível 🛑
- Funções que lançam erro ou entram em loop infinito.
Null e Undefined ❓
- No modo
strict, eles são tratados como erros se você não os prever. - Evita erros de "null references".
Resumo 🏁
- Tipos Primitivos
- Arrays e Tuplas
- Enums e Any/Unknown
Próxima Aula: Tipos Avançados!
Vamos ver Uniões, Interseções e mais. 🚀
Aula 03 - Tipos Avançados 🧩
O Desafio da Flexibilidade 🤸
- Nem tudo no mundo é preto no branco (string ou number).
- Às vezes um dado pode ser várias coisas.
Union Types (União) 🤝
- O operador
|(ou). - Permite que uma variável aceite mais de um tipo.
Uniões na Prática 📦
- Útil para: Status de API, IDs, Cores de tema.
Type Aliases (Apelidos) 🏷️
- Em vez de repetir
string | number, criamos um nome.
Aliases de Objetos 🏗️
- Organização e legibilidade.
Intersection Types (Interseção) 🔗
- O operador
&(e). - Combina tipos existentes em um novo.
Interseção vs União ⚖️
- União (
|): Um ou outro. - Interseção (
&): Todos juntos.
Literal Types (Literais) 🎯
- Restringe uma variável a valores exatos.
Segurança com Literais 🛡️
- Evita erros de digitação (ex: "esquerada").
Narrowing: Estreitando Tipos 🔍
- O TS analisa a lógica do
ifpara saber o tipo exato.
function processar(id: number | string) {
if (typeof id === "string") {
// Aqui o TS sabe que é string!
}
}
Type Guards Reais 🕵️
- Além de
typeof: instanceof(para classes)- Operador
in(para propriedades)
Funções como Guards 🛡️
- Podemos criar funções que retornam um booleano de tipagem.
O operador as (Type Assertion) ⚠️
- Avisar ao TS: "Pode confiar, eu sei que isso é X".
- Use com cautela!
Non-Null Assertion ‼️
- O ponto de exclamação
!. - Garante que algo não é nulo/indefinido.
Discriminated Unions 🆔
- Adicionar um campo "tag" para facilitar a distinção entre tipos em uma união.
Exemplo: API Response 📡
graph TD;
Response[API Response] --> Success[Tipo: Success];
Response --> Error[Tipo: Error];
Success --> UI[Renderizar Dados];
Error --> Log[Mostrar Alerta];
Resumo 🏁
- Union e Intersection
- Type Aliases
- Narrowing e Type Guards
Próxima Aula: Interfaces!
Vamos modelar sistemas complexos. 🚀
Aula 04 - Interfaces e Modelagem de Domínio 🏗️
O que são Interfaces? 🧩
- Contratos para o seu código.
- Definem a "forma" de um objeto.
Diferença: Interface vs Type ⚖️
- Interface: Focada em objetos e extensibilidade (POO).
- Type: Mais flexível (Unions, Primitivos, Interseções).
Sintaxe Básica ✍️
Propriedades Opcionais ❓
- Use
?para campos que podem não existir.
Propriedades Readonly 🔒
- Proteção contra alterações após a criação.
Extensibilidade (Herança) 🌲
- Interfaces podem herdar de outras.
Herança Múltipla 🌳
- Sim, uma interface pode estender várias!
Implementação em Classes 🏛️
- O contrato que a classe deve seguir.
Declaration Merging 🤝
- Interfaces com o mesmo nome na mesma pasta se fundem automaticamente.
Quando usar Merging? 🛠️
- Ideal para estender definições de bibliotecas externas (como adicionar um campo no
Requestdo Express).
Modelagem de Domínio 🗺️
- Traduzindo a realidade em interfaces.
- Cliente, Produto, Pedido, Pagamento.
Exemplo: Pedido de Ecommerce 🛒
classDiagram
Pedido --> Cliente
Pedido --> "many" ItemPedido
ItemPedido --> Produto
class Produto{ +id, +nome, +preco }
Interfaces para Funções 📞
- Sim, interfaces podem descrever a assinatura de uma função.
Boas Práticas de Nomeação ✍️
- Use nomes substantivos (Usuario, Produto).
- A convenção do prefixo
I(ex:IUsuario) é opcional, mas herdada do C#.
Interface vs Model 🏗️
- No TS, usamos interfaces para definir a estrutura dos dados que trafegam na nossa aplicação.
Segurança de Tipo Total 🛡️
- Com interfaces bem definidas, erros de "undefined" somem do seu projeto.
Resumo 🏁
- Definição de Interfaces
- Extensão (extends)
- Interface vs Type Alias
Próxima Aula: Classes e POO!
Vamos entrar no mundo dos objetos. 🚀
Perguntas? ❓
Aula 05 - Classes e Programação Orientada a Objetos 🏛️
O que é POO? 🧱
- Programação Orientada a Objetos.
- Organizar o código em "moldes" (classes) e "exemplares" (objetos).
Classes no TypeScript 🏗️
- Diferente do JS puro, o TS permite tipar atributos e usar modificadores.
Modificadores de Acesso 🔑
- public: Acesso em qualquer lugar (padrão).
- private: Acesso apenas dentro da classe.
- protected: Acesso na classe e em suas subclasses.
Shorthand Properties 🏎️
- Mais rápido e limpo!
Readonly em Classes 🔒
- Propriedades que só podem ser mudadas no construtor.
Getters e Setters 🛡️
- Interceptam o acesso aos dados.
Herança (Extends) 🌲
- Reutilize código de classes base.
O Método super() 🦸
- Chama o construtor da classe pai.
- Obrigatório se a classe filha tiver seu próprio construtor.
Polimorfismo 🎭
- "Muitas formas".
- Uma subclasse pode sobrescrever métodos do pai.
Sobreescrita de Métodos ✍️
Classes Abstratas ☁️
- Moldes que não podem ser usados sozinhos.
- Servem apenas para serem herdados.
Métodos Abstratos 📋
- O pai define o que deve ser feito.
- A filha decide como fazer.
Membros Estáticos (static) ⚡
- Pertencem à classe, não ao objeto (instância).
- Ex:
Math.random().
Diagramas de Classe 📊
classDiagram
Animal <|-- Cachorro
Animal : +nome string
Animal : +falar()
class Cachorro{
+falar()
}
Vantagens no TypeScript 💎
- Checagem rigorosa de quem pode acessar o quê.
- Melhores sugestões de refatoração no editor.
Encapsulamento Real 🛡️
- Ocultar complexidade interna e expor apenas o necessário.
Composição vs Herança 🧩
- Dica: Prefira compor objetos pequenos em vez de criar hierarquias gigantes de herança.
Resumo 🏁
- Modificadores (Public, Private, Protected)
- Herança e Polimorfismo
- Classes Abstratas
Próxima Aula: Generics!
Vamos criar código universal e seguro. 🚀
Perguntas? ❓
Aula 06 - Generics (Programação Genérica) 📦
O que são Generics? 🧬
- Componentes que funcionam com vários tipos de dados.
- Mantêm a segurança sem usar
any.
O Problema do any 🌪️
- Perdemos o autocompletar.
- O TypeScript para de nos proteger.
A Sintaxe <T> ✍️
- O Diamante (Diamond Operator).
- "T" representa um tipo que será definido depois.
Exemplo: Função Genérica 📞
Como usar Generics 🛠️
- Especificando o tipo:
Identity<string>("Olá"). - Deixando o TS inferir:
Identity(10).
Generics em Arrays 📚
- Já vimos isso:
Array<string>é um Generic!
Múltiplos Tipos Genéricos 👥
- Podemos ter mais de um.
<T, U, K>.
Generic Constraints (Restrições) ⛓️
- Limitar quais tipos podem ser usados.
- Usamos a palavra-chave
extends.
Exemplo: Restrição de Propriedade 🛡️
interface PossuiLength { length: number; }
function logSize<T extends PossuiLength>(arg: T) {
console.log(arg.length);
}
Classes Genéricas 🏗️
- Criar moldes que se adaptam ao dado neles guardado.
Interfaces Genéricas 🧩
- Muito comum para respostas de servidores.
Generics com Valor Padrão 🎁
- Podemos definir um tipo "default".
Por que usar Generics? 💎
- Reutilização de código masiva.
- Tipagem 100% segura.
- Menos código duplicado.
Onde encontramos Generics? 🕵️
- Bancos de dados (Prisma, TypeORM).
- Consumo de APIs (Axios).
- Hooks do React (
useState<User>()).
Visualizando Generics 📊
graph LR;
Func[Função Genérica] -- "Passa String" --> Res1[Retorna String];
Func -- "Passa Number" --> Res2[Retorna Number];
style Func fill:#f9f,stroke:#333
Boas Práticas ✍️
- Não use Generics se não for necessário (KISS).
- Use nomes curtos como T, U, V ou descriptivos como TData, TResponse.
Erros Comuns ❌
- Tentar usar métodos específicos de um tipo (ex:
.toUpperCase()) sem antes de fazer a restrição comextends.
Generics vs Unions ⚖️
- Unions: Aceita A ou B.
- Generics: "Prende" o tipo do início ao fim da execução.
Resumo 🏁
- Conceito de Generics
- Constraints (extends)
- Classes e Interfaces Genéricas
Próxima Aula: Utility Types!
Vamos manipular tipos como magos. 🚀
Perguntas? ❓
Aula 07 - Utility Types e Manipulação de Tipos ⚙️
O que são Utility Types? 🛠️
- Atalhos integrados no TypeScript.
- Transformam tipos existentes em novos tipos de forma fácil.
Partial<T> (Opcional) ❓
- Torna todas as propriedades de um tipo opcionais.
Exemplo: Update de Usuário 🔄
- Frequentemente usado em formulários de edição onde você só muda alguns campos.
Required<T> (Obrigatório) ❗️
- O oposto do Partial.
- Garante que todas as propriedades existam, mesmo as marcadas com
?.
Readonly<T> (Imutável) 🔒
- Transformar todas as propriedades em apenas leitura.
Curiosidade 🧠
Readonlysó impede a alteração via TypeScript. No JavaScript compilado, o valor ainda pode ser alterado se não usarmos técnicas de JS comoObject.freeze.
Pick<T, K> (Escolher) 🎯
- Selecionar apenas algumas propriedades de um tipo.
Omit<T, K> (Omitir) 🚫
- Remove propriedades específicas de um tipo.
Pick vs Omit ⚖️
- Use
Pickquando quiser poucas coisas de um tipo grande. - Use
Omitquando quiser remover poucas coisas de um tipo grande.
Record<K, T> (Mapear) 🗺️
- Criar um objeto de chave-valor bem definido.
Exclude<T, U> e Extract<T, U> 🔍
- Exclude: Remove tipos de uma união.
- Extract: Mantém apenas tipos comuns entre uniões.
ReturnType<T> 📞
- Captura o tipo de retorno de uma função automaticamente.
Por que usar estes utilitários? 💎
- Evita repetição de código (DRY).
- Se o tipo base mudar, os utilitários se atualizam sozinhos!
Mapped Types: Por debaixo dos panos 🪄
- Os Utility Types usam iteração sobre as chaves do objeto para funcionar.
Visualizando as Transformações 📊
graph LR;
Original[User Full] -- "Omit 'senha'" --> Public[User Public];
Original -- "Partial" --> Update[User Update Form];
Original -- "Pick 'id' | 'nome'" --> Summary[User Summary];
Dica: Documentação Oficial 📚
- O TypeScript possui dezenas de utilitários. Sempre consulte antes de criar um tipo complexo manualmente.
Utility Types em APIs 📡
- Muito útil para filtrar dados sensíveis antes de enviá-los ao frontend.
Refatoração com Utilitários 🛠️
- Reduza suas 200 linhas de interfaces para 50 usando composição e utilitários.
Resumo 🏁
- Partial, Required e Readonly
- Pick e Omit
- Record e ReturnType
Próxima Aula: Manipulação Avançada!
Vamos ver Keyof, Infer e Conditional Types. 🚀
Perguntas? ❓
Aula 08 - Manipulação Avançada de Tipos 🧪
Subindo o Nível 🚀
- Hoje vamos além das interfaces simples.
- Veremos como o TS pode ser dinâmico e "mágico".
O operador keyof 🔑
- Extrai todas as chaves (nomes das propriedades) de um tipo.
keyof na Prática 🛠️
- Criar funções que acessam propriedades de objetos com garantia de que a chave existe.
Indexed Access Types 📂
- "Olhar" para o tipo de uma propriedade específica.
Conditional Types (Se/Então) ⚖️
- Tipos que decidem seu formato baseados em condições.
- Sintaxe:
T extends U ? X : Y.
Exemplo: Verificação de Tipo 🔍
A palavra-chave infer 🕵️
- Capturar um tipo de "dentro" de outro durante uma checagem condicional.
Exemplo: Extrair Tipo do Array 📦
Template Literal Types 🔠
- Criar uniões de strings dinâmicas usando crases.
type Evento = "click" | "hover";
type EventoDinamico = `on${Capitalize<Evento>}`;
// "onClick" | "onHover"
Manipulando Nomes de Propriedades ✍️
- Utilitários:
Uppercase,Lowercase,Capitalize,Uncapitalize.
Mapped Types Avançados 🗺️
- Mudar o nome das chaves durante a criação do tipo.
Recursividade em Tipos 🔁
- Um tipo pode chamar a si mesmo! (Cuidado com loops infinitos).
Utilitário: Exclude e Extract Revisitados 🛠️
- Por baixo dos panos todos eles usam tipos condicionais.
Visualizando Lógica de Tipos 📊
graph TD;
T{T extends string?};
T -- Sim --> R1[Tipo: String];
T -- Não --> R2[Tipo: Outro];
Onde isso é usado? 💎
- Filtros de busca tipados automaticamente.
- Transformadores de dados complexos.
- Frameworks como NestJS e bibliotecas de Schema (Zod).
Por que aprender isso? 🏆
- Para construir ferramentas (libraries) que outros desenvolvedores usarão.
- Para entender as mensagens de erro mais cabulosas do TS.
Dica: Não abuse! 🛑
- Código de tipagem muito complexo pode ser tão difícil de manter quanto código de lógica complexa.
Deep Dive: infer 🌊
- Pense no
infercomo uma variável temporária que o TS preenche para você.
Resumo 🏁
- keyof e Acesso Indexado
- Tipos Condicionais e infer
- Template Literal Types
Próxima Aula: Módulos e Organização!
Vamos organizar nosso caos. 🚀
Perguntas? ❓
Aula 09 - Módulos e Organização Profissional 📁
Organizando o Caos 🌪️
- Conforme o projeto cresce, não podemos ter tudo em um arquivo só.
- Precisamos de uma estrutura modular e escalável.
ES Modules (Import/Export) 📦
- O padrão moderno do JavaScript.
export: Disponibilizar algo.import: Trazer algo de outro arquivo.
Named Exports (Exportações Nomeadas) 🏷️
- Várias exportações por arquivo.
Default Export (Exportação Padrão) 🥇
- Apenas uma por arquivo.
- Não precisa de chaves
{}ao importar.
Barrel Files (index.ts) 🛢️
- Concentrar exportações de uma pasta em um único ponto.
- Simplifica a vida de quem consome.
Exemplo: Pasta de Controllers 🎮
- Em vez de importar de 5 arquivos, importa tudo do
index.ts.
Namespaces (Espaços de Nomes) 🏘️
- Uma forma antiga de organizar código TS.
- Evitam colisões de nomes globais.
- Dica: Prefira Módulos para projetos modernos.
Path Aliases (Apelidos de Caminho) 🔗
- Chega de
../../../. - Use
@models/Usuarioem vez de caminhos relativos infinitos.
Configurando Aliases ⚙️
- Feito no
tsconfig.json.
Estrutura de Pastas Profissional 🏗️
Módulos de Terceiros 📦
- Instalando tipos:
@types/nome-da-biblioteca. - Ex:
@types/node,@types/express.
Tipagem de Bibliotecas Legadas 🕰️
- Como criar seu próprio arquivo
.d.tsse a biblioteca não tiver tipos.
Declare: O comando de confiança 🤝
declare var jQuery: any;- Avisa ao TS que algo existe globalmente (ex: via CDN).
Modificadores de Acesso de Módulos 🔒
- Se você não exportar, fica privado ao arquivo.
- Encapsulamento em nível de sistema de arquivos!
Re-exportação 🔄
export * from './outro-arquivo';- Útil para criar bibliotecas e SDKs.
Visualizando o Fluxo de Módulos 📊
graph LR;
User[User.ts] -- Export --> Index[index.ts];
App[App.ts] -- Import --> Index;
style Index fill:#f96,stroke:#333
Scripts NPM de Organização 📝
lint: Verificar estilo.format: Ajustar código automaticamente (Prettier).
Barrel Files: Menos é Mais! ⚖️
- Cuidado com o "Circula Dependency" ao usar Barrel Files em excesso.
Resumo 🏁
- Import / Export
- Barrel Files e Namespaces
- Path Aliases e Organização de Pastas
Próxima Aula: TypeScript com Node.js!
Vamos para o Backend. 🚀
Perguntas? ❓
Aula 10 - TypeScript com Node.js (Backend) 🟢
TypeScript no Servidor 🖥️
- Segurança total desde a requisição até o banco de dados.
Setup de um Projeto Backend 🛠️
- Instalar:
express,ts-node-dev,@types/node,@types/express.
Por que Node + TS? 🚀
- Autocompletar nos métodos do Express.
- Refatoração de APIs de larga escala.
- Redução de erros 500 (Internal Server Error).
Configurando o Servidor 📡
Tipando Requisições (Request) 📥
- Garantir que o
bodyouparamstenham o formato correto.
interface UserBody { nome: string; }
app.post('/', (req: Request<{}, {}, UserBody>, res: Response) => { ... });
Tipando Respostas (Response) 📤
- Forçar que sua API retorne sempre o mesmo padrão JSON.
O uso de DTOs 🔄
- Data Transfer Object.
- Simplesmente um tipo que define o que entra e o que sai da aplicação.
Camada de Serviços (Services) 🏗️
- Tire a lógica de dentro da rota!
- Crie classes de serviço tipadas.
Middlewares Tipados 🛡️
- Autenticação e logs.
- O uso da
NextFunction.
Tratamento de Erros Profissional ⚠️
- Criar classes de erro customizadas (AppError).
- Middleware global de erros para capturar tudo de forma tipada.
Banco de Dados com TS 💾
- Ferramentas modernas: Prisma ou TypeORM.
- Elas geram os tipos automaticamente a partir do seu esquema!
Exemplo: Fluxo de Dados Backend 📊
graph LR;
Client[Cliente] -- Requisição --> Router[Rotas];
Router -- DTO --> Controller[Controller];
Controller --> Service[Service];
Service --> DB[(Banco de Dados)];
Scripts de Desenvolvimento 📝
"dev": "ts-node-dev --respawn --transpile-only src/server.ts"
Variáveis de Ambiente Tipadas 🗝️
- Como garantir que seu
process.envtenha as chaves necessárias.
Deploy de Código Backend 🚀
- Transpilação com
tsc. - Execução com
node dist/server.js.
Performance: --transpile-only 🏎️
- Em desenvolvimento, ignoramos os erros de tipo para rodar mais rápido; o editor já nos avisou antes!
CORS e Segurança 🔒
- Tipando as configurações de Cross-Origin.
Documentação Automática (Swagger) 📖
- Como gerar docs a partir dos seus tipos TS.
Resumo 🏁
- Express + TS Setup
- Tipagem de Request/Response
- Organização em Middlewares e Services
Próxima Aula: TypeScript com Frontend Moderno!
Vamos para o React. 🚀
Perguntas? ❓
Aula 11 - TypeScript com Frontend Moderno ⚛️
TypeScript no Navegador 🌐
- Foco em: Componentização e Segurança de Dados.
Por que Frontend + TS? 🚀
- Saber exatamente quais Props um componente recebe.
- Evitar o clássico "undefined is not a function" na UI.
- Estado (State) 100% previsível.
Tipando Props 🧩
- O contrato entre o componente pai e o filho.
Componentes Funcionais 🧱
- Como declarar:
const MeuComp = ({ label }: Props) => { ... }
Hooks: useState 🎣
- Inferência vs Explícito.
Hooks: useRef 🔍
- Manipulando o DOM com segurança.
Eventos de Formulário 📝
- Tipos específicos:
ChangeEvent,FormEvent.
Context API Tipada 🌍
- Estado global seguro.
interface Contexto { tema: string; user: User; }
const GlobalContext = createContext<Contexto | undefined>(undefined);
Hooks Customizados Genéricos 🛠️
useLocalStorage<T>: Reutilização total!
Estilização (CSS-in-JS) 🎨
- Tipando temas no Styled Components ou Tailwind.
Consumo de API no Front 📡
- Onde realizar a chamada (useEffect) e como guardar no estado tipado.
Componentes Genéricos de UI 🔘
- Tabelas, Listas e Grids que aceitam qualquer dado.
O operador as no DOM ⚠️
e.target as HTMLButtonElement.- Necessário às vezes para acessar propriedades específicas.
Hierarquia de Componentes 📊
graph TD;
App[App.tsx] --> AuthProvider[Context: Auth];
AuthProvider --> Dashboard[Página: Dashboard];
Dashboard --> UserCard[Componente: UserCard];
Erros comuns no Frontend ❌
- Esquecer de tipar o
nullinicial douseState.
Melhores ferramentas 🛠️
- Vite + TypeScript (O padrão atual).
- ESLint + Prettier.
Tipagem de Bibliotecas UI 📚
- Material UI, Shadcn/UI, Radix.
Testando Componentes 🧪
- Introdução rápida ao Testing Library com TS.
Resumo 🏁
- Props e State Tipados
- Hooks e Context API
- Componentes Genéricos
Próxima Aula: Integração com APIs!
Vamos conectar tudo. 🚀
Perguntas? ❓
Aula 12 - Integração com APIs e Tipagem de Dados Externos 📡
O Mundo Externo é Incerto 🌪️
- O TypeScript não roda na internet.
- Dados vindos de APIs podem estar errados ou incompletos.
Fetch e Axios com Generics 🌐
- Informar ao TS o que esperamos receber.
Tipagem de Respostas de API 📥
- Crie interfaces que reflitam EXATAMENTE o JSON da API.
O Padrão DTO Revisitado 🔄
- Diferença entre o que a API envia e o que sua aplicação precisa.
Mapeamento de Dados (Mappers) 🗺️
- Funções que convertem a resposta da API para o seu modelo interno.
Por que mapear? 💎
- Se a API mudar um campo de nome, você só altera o Mapper, não o app inteiro!
Validação em Tempo de Execução 🛡️
- O TypeScript desaparece no build.
- Precisamos de algo que valide os dados enquanto o usuário usa o app.
Conhecendo o Zod 🛡️
- Biblioteca de Schema Validation.
- "Criação de tipos que validam".
Exemplo: Schema Zod ✍️
Inferencia do Zod 🧠
- Gere seu tipo TS a partir do Schema!
Tratamento de Erros de Rede ⚠️
- Tipando erros HTTP (404, 500, etc).
Axios Interceptors 🛠️
- Adicionar cabeçalhos (Auth) e tratar erros globalmente com tipagem.
Estado de Loading e Error ⏳
- Criar uniões para representar os estados de uma requisição.
Visualizando o Ciclo da Requisição 📊
graph LR;
App[App/Store] -- Request --> Axios[Axios];
Axios -- JSON --> Zod{Validação};
Zod -- OK --> Mapper[Mapper/App];
Zod -- Erro --> UI[Alerta de Erro];
React Query e SWR ⚡
- Bibliotecas que facilitam a vida com TS, Cache e estados de carregamento.
Tipagem de Parâmetros de Busca (Query Params) 🔍
/users?ordenar=nome&limite=10.
Mocking de APIs para Testes 🎭
- Usando MSW (Mock Service Worker) para simular respostas tipadas.
O Perigo do any em APIs 🛑
- NUNCA deixe o retorno da API como
any. É o lugar onde mais acontecem bugs silenciosos.
Resumo 🏁
- Axios + Generics
- Mapeamento e DTOs
- Validação com Zod
Próxima Aula: Testes com TypeScript!
Vamos garantir a estabilidade. 🚀
Perguntas? ❓
Aula 13 - Testes com TypeScript 🧪
Por que Testar? 🛡️
- Garantir que o código faz o que deve fazer.
- Evitar que bugs antigos voltem (regressão).
- Confiança para refatorar.
O Ecossistema Jest 🎪
- Jest: O framework de testes "tudo em um".
ts-jest: O motor que permite rodar TS no Jest.
Tipos de Teste 🧱
- Unitário: Pequenas partes (funções).
- Integração: Várias partes juntas (API + DB).
- E2E (Ponta a Ponta): O fluxo completo do usuário no navegador.
Anatomia de um Teste 🔍
describe('Calculadora', () => {
it('deve somar dois números', () => {
expect(somar(2, 2)).toBe(4);
});
});
Configurando o Jest ⚙️
jest.config.js- Preset:
ts-jest.
Testando Funções Assíncronas ⏳
async/awaitnos testes.
O Poder dos Mocks 🎭
- Simular dependências que não queremos usar nos testes (ex: banco de dados real).
Mockando Módulos 🧩
Spies (Espiões) 🕵️
- Verificar se uma função foi chamada, quantas vezes e com quais argumentos.
Testando Erros ⚠️
- Garantir que seu código lança as exceções corretas nos momentos certos.
Cobertura de Código (Coverage) 📊
- Saber quais partes do projeto ainda não foram testadas.
Testes de Integração com Supertest 🔗
- Testar rotas do Express sem precisar subir o servidor de verdade.
Hooks de Teste 🪝
beforeEach: Rodar algo antes de cada teste (ex: limpar banco).afterAll: Rodar após tudo (ex: fechar conexões).
TDD (Test Driven Development) 🔄
- Escrever o teste antes do código.
graph LR;
Red[Vermelho: Falha] --> Green[Verde: Passa];
Green --> Refactor[Refatorar];
Refactor --> Red;
Vantagens no TypeScript 💎
- O próprio compilador já é um "teste de tipo" constante.
- Os testes unitários focam na lógica, enquanto o TS foca nos contratos.
Testando o Frontend (React) ⚛️
- React Testing Library.
- Focar no comportamento do usuário, não na implementação.
CI/CD e Testes 🚀
- Rodar os testes automaticamente em cada
git push.
Dica: Testes Legíveis 📖
- O nome do teste deve ser uma frase que explique o cenário e o resultado esperado.
Resumo 🏁
- Jest e ts-jest
- Mocks e Spies
- TDD e Integração
Próxima Aula: Padrões de Projeto!
Vamos arquitetar como profissionais. 🚀
Perguntas? ❓
Aula 14 - Padrões de Projeto com TypeScript 🛡️
Software de Alta Qualidade 🏆
- Não basta funcionar; o código deve ser fácil de manter e evoluir.
O que são Design Patterns? ♟️
- Soluções reutilizáveis para problemas recorrentes no design de arquitetura.
Padrão Repository 🏛️
- Isolar a lógica de persistência de dados.
- O app não sabe se os dados vêm do SQL, Mongo ou Memória.
Implementando um Repository 🏗️
- Use Interfaces para definir o contrato.
Service Layer 🏗️
- Onde vive a Lógica de Negócio.
- Os serviços orquestram os repositórios.
Dependency Injection (DI) 💉
- Injetar dependências via construtor.
- Classes desacopladas e fáceis de testar.
Factory Pattern 🏭
- Centralizar a lógica de criação de objetos complexos.
Strategy Pattern 🎯
- Trocar algoritmos em tempo de execução.
- Ex: Diferentes formas de cálculo de desconto.
Singleton Pattern 🥇
- Garantir que uma classe tenha apenas uma instância (ex: Configuração, Database).
Observer Pattern 👁️
- Um objeto notifica outros sobre mudanças de estado.
Decorators em TypeScript 🎀
- Adicionar metadados ou comportamentos a classes e métodos de forma elegante (muito usado no NestJS).
Onde usar cada padrão? 🗺️
graph TD;
API[API/Routes] --> Service[Service Layer - Business Logic];
Service --> Repository[Repository Pattern - Data];
Service --> Factory[Factory - Object Creation];
Service --> Strategy[Strategy - Algorithms];
Vantagens dos Padrões 💎
- Linguagem comum entre desenvolvedores.
- Código mais organizado e previsível.
- Facilidade de expansão.
Composição sobre Herança 🧩
- Use padrões para compor comportamentos em vez de criar cadeias longas de classes pais.
Padrões no Frontend ⚛️
- Custom Hooks (são um tipo de Factory/Service).
- Render Props e HOCs (Padrão Decorator/Wrapper).
Dica: Não "Super-Arquitete" 🛑
- Use padrões apenas quando houver um problema real para resolver. Evite complexidade desnecessária.
Padrões de Criação, Estruturais e Comportamentais 📂
- As três grandes categorias do GoF (Gang of Four).
Resumo 🏁
- Repository e Service
- Injeção de Dependência
- Factory e Strategy
Próxima Aula: Clean Code e Arquitetura!
O refino final do seu código. 🚀
Perguntas? ❓
Aula 15 - Clean Code e Arquitetura 📐
Código para Humanos 👥
- "Qualquer tolo consegue escrever código que um computador entenda. Bons programadores escrevem código que humanos entendam."
O que é Clean Code? ✨
- Um código que se lê como uma prosa bem escrita.
Princípios SOLID 💎
Cinco pilares da arquitetura orientada a objetos: - Single Responsibility - Open/Closed - Liskov Substitution - Interface Segregation - Dependency Inversion
S: Responsabilidade Única 🎯
- Uma classe/função deve ter apenas UM motivo para mudar.
O: Aberto para Extensão, Fechado para Mudança 🔓
- Adicione novas funcionalidades sem quebrar o que já existe.
I: Segregação de Interfaces 🧩
- Interfaces pequenas e específicas são melhores que interfaces "gordas".
D: Inversão de Dependência 💉
- Dependa de abstrações, não de implementações.
DRY: Don't Repeat Yourself 🔁
- Evite duplicar lógica em vários lugares.
KISS: Keep It Simple, Stupid! 🧠
- Não complique o que pode ser simples.
YAGNI: You Ain't Gonna Need It 🚫
- Não adicione funcionalidades "para o futuro" que você ainda não precisa.
Nomes Significativos ✍️
- Variáveis e funções devem dizer o que fazem sem precisar de comentários.
Funções Pequenas 🤏
- Máximo de 20 linhas.
- Se a função está grande, ela provavelmente faz coisas demais.
Comentários: O Mal Necessário ⚠️
- Se você precisa comentar o que o código faz, o código não está limpo o suficiente. Comente o "porquê" de decisões complexas.
Arquitetura em Camadas 🏢
graph TD;
UI[Interface / API] --> Application[Camada de Aplicação];
Application --> Domain[Camada de Domínio];
Domain --> Infra[Infraestrutura / BD];
DDD: Domain-Driven Design 🗺️
- O coração do software é o Domínio (regras de negócio).
Entidades e Value Objects 💎
- Entidades: Têm ID (Ex: Usuário).
- Value Objects: Definidos pelos seus atributos (Ex: Endereço).
Refatoração Contínua 🧹
- Aplique a "Regra do Escoteiro": Deixe o código sempre um pouco melhor do que o encontrou.
Dívida Técnica 💸
- Código "sujo" hoje é juros que você pagará amanhã em forma de bugs e lentidão.
Resumo 🏁
- Princípios SOLID
- Regras de Clean Code (Nomes, Tamanho)
- Arquitetura em Camadas
Próxima Aula: Projeto Final e Deploy!
Vamos colocar tudo no ar. 🚀
Perguntas? ❓
Aula 16 - Projeto Final e Deploy 🚀
O Grand Finale! 🎓
- Hora de colocar em prática tudo o que aprendemos.
O Projeto: E-commerce Fullstack 🛒
- Backend: Node.js + Express + TS.
- Frontend: React + Hooks + TS.
- Integração: Axios + Zod.
- Qualidade: Jest.
O Ciclo da Produção 🏗️
graph LR;
Code[Código TS] --> Build[Compilação tsc];
Build --> Test[Testes CI];
Test --> Artifact[Artefato JS];
Artifact --> Deploy[Servidor / Nuvem];
Preparando o Build 📦
- O comando:
npm run build. - Gerando a pasta
dist/.
Scripts de Produção 📝
start: Executar o código compilado comnode.
Variáveis de Ambiente (.env) 🗝️
- Senhas de banco, portas do servidor, chaves de API.
- Nunca envie seu
.envpara o Git!
Dockerizando a Aplicação 🐳
- Padronização total do ambiente.
# Exemplo básico
FROM node:18
WORKDIR /app
COPY . .
RUN npm install && npm run build
CMD ["node", "dist/index.js"]
Deploy Frontend 🌐
- Hostings Estáticos: Vercel, Netlify.
- Alta performance via CDNs globais.
Deploy Backend 🖥️
- Plataformas: Railway, Render, AWS, Heroku.
Continuous Deployment (CD) 🔄
- Push no GitHub = Deploy automático.
Monitoramento e Logs 📊
- Saber quando o site cai e por que.
Documentação Final 📖
- O
README.mdé a vitrine do seu projeto. - Inclua instruções de como rodar e quais tecnologias usou.
Dicas para o Carreira 💼
- Coloque o código no seu Portfolio / GitHub.
- Mostre que você usa TypeScript Profissionalmente.
Além do Curso 🚀
- O aprendizado nunca para!
- Explore: NestJS, Next.js, GraphQL, Microservices.
Parabéns! 🎉
- Você agora domina o TypeScript Profissional.
Vamos para a Apresentação? 📊
- Mostre seu projeto para a turma.
Resumo 🏁
- Estrutura de Build
- Docker e Nuvem
- Projeto Completo
Obrigado! ❤️
Continue codando e evoluindo.
Perguntas Finais? ❓
Setups
Guias de Instalação 🛠️
Prepare seu ambiente de desenvolvimento.
-
Ferramentas Iniciais
Comece por aqui.
-
Linguagens Corporativas
Para grandes sistemas.
-
Sistemas e Mobile
Performance e Apps.