Engenharia de IA Aplicada à Programação Web
Aula 1 de 6
Navegar por módulos e aulas
  1. 01 Fundamentos da Web
  2. 02 JavaScript moderno
  3. 03 TypeScript, Git e qualidade
  4. 04 Angular
  5. 05 Node.js, NestJS e APIs
  1. 3.1 Introdução ao TypeScript
  2. 3.2 Interfaces, aliases e contratos
  3. 3.3 Unions, narrowing e generics
  4. 3.4 Configuração, lint e formatação
  5. 3.5 Git, branches e pull requests
  6. 3.6 Testes, documentação e projeto

Módulo 3 · Aula 3.1

Introdução ao TypeScript

2 horas Teoria + laboratório TypeScript, Git e qualidade
Ver fonte Markdown

Identificação

Introdução

O que é TypeScript?

TypeScript é uma linguagem construída sobre JavaScript. Ela adiciona um sistema de tipos estáticos e ferramentas de análise:

const courseName: string = "Engenharia de IA";
const completedLessons: number = 8;

Todo JavaScript válido é, em termos gerais, ponto de partida para TypeScript. O TypeScript analisa o código antes da execução e ajuda a encontrar inconsistências.

TypeScript substitui JavaScript?

Não. O navegador executa JavaScript. O código TypeScript normalmente passa por um compilador ou ferramenta de compilação que remove os tipos e gera JavaScript:

app.ts → compilador TypeScript → app.js → navegador

Aprender TypeScript não elimina a necessidade de compreender JavaScript. Condições, funções, arrays, objetos, Promises e o DOM continuam sendo JavaScript.

TypeScript é framework?

Não. TypeScript é uma linguagem e um conjunto de ferramentas. Angular é um framework que utiliza TypeScript, mas TypeScript pode ser usado sem Angular.

O que significa tipagem estática?

Significa que o código pode ser analisado antes de executar:

let estimate: number = 2;
estimate = "duas horas";

O compilador sinaliza que uma string não pode ser atribuída a number.

JavaScript continua tendo tipos em execução, mas eles pertencem aos valores e podem mudar dinamicamente. TypeScript adiciona contratos verificados durante o desenvolvimento.

TypeScript impede todos os erros?

Não. Ele ajuda a detectar uma classe importante de problemas, mas não prova que todo comportamento está correto:

function divide(a: number, b: number): number {
  return a / b;
}

divide(10, 0); // permitido pelo tipo, mas exige regra de negócio

Também não substitui testes, validação, segurança, revisão ou observabilidade.

Os tipos existem no navegador?

Normalmente, não. Eles são removidos na compilação:

const estimate: number = 2;

JavaScript gerado:

const estimate = 2;

Isso é chamado de apagamento de tipos.

TypeScript valida JSON de uma API?

Não automaticamente:

const response = await fetch("/api/tasks");
const data = await response.json();

O servidor pode enviar um formato diferente do tipo declarado. Dados externos precisam ser validados em tempo de execução.

Onde isso aparece no projeto?

O laboratório mostrará lado a lado o contrato TypeScript e o JavaScript executado. Um formulário demonstrará que HTML fornece strings e que conversão e validação continuam necessárias.

Objetivos

Ao final da aula, o aluno deverá conseguir:

  1. explicar o papel do TypeScript;
  2. diferenciar TypeScript, JavaScript e framework;
  3. descrever compilação e apagamento de tipos;
  4. diferenciar erro estático e erro em execução;
  5. utilizar inferência e anotações;
  6. tipar primitivas, arrays, objetos e funções;
  7. reconhecer any e unknown;
  8. entender que tipos não validam dados externos;
  9. ler uma configuração TypeScript básica;
  10. relacionar código .ts à saída .js.

Pré-requisitos

  • Módulos 1 e 2 concluídos;
  • JavaScript moderno, módulos e testes;
  • editor de código;
  • Node.js e npm serão utilizados nas próximas etapas de configuração.

Pergunta orientadora

Como detectar incompatibilidades antes de executar sem confundir tipos estáticos com validação real dos dados?

Roteiro sugerido

Etapa Duração
TypeScript, JavaScript e compilação 20 min
Inferência e anotações 25 min
Arrays, objetos e funções 30 min
any, unknown e dados externos 20 min
Laboratório 20 min
Revisão 5 min

1. Extensões de arquivo

  • .js: JavaScript;
  • .ts: TypeScript;
  • .tsx: TypeScript com sintaxe JSX, comum em algumas bibliotecas de interface;
  • .d.ts: declarações de tipos.

Nosso primeiro arquivo será app.ts.

2. Anotação de tipo

const title: string = "Estudar TypeScript";
let estimate: number = 2;
let completed: boolean = false;

A anotação aparece depois do nome.

Evite tipos escritos como construtores:

const title: String = "texto";

Prefira primitivas em minúsculas:

const title: string = "texto";

3. Inferência

TypeScript frequentemente deduz o tipo:

const title = "Estudar TypeScript";
let estimate = 2;

Não é necessário anotar tudo. Use anotações quando:

  • o contrato público precisa ficar explícito;
  • o tipo não pode ser inferido corretamente;
  • declaramos parâmetros;
  • queremos impedir uma inferência estreita ou ampla demais;
  • a anotação melhora a compreensão.

4. const e tipos literais

const status = "todo";

Como a constante não será reatribuída, TypeScript pode inferir o literal "todo", não apenas string.

Com let:

let status = "todo";

O tipo normalmente é ampliado para string, pois outros textos podem ser atribuídos.

5. Tipos primitivos

const title: string = "Tarefa";
const estimate: number = 3;
const completed: boolean = false;
const identifier: bigint = 10n;
const token: symbol = Symbol("token");

null e undefined possuem tipos próprios. Com configuração estrita, precisam ser tratados explicitamente.

6. Arrays

const tags: string[] = ["typescript", "curso"];
const estimates: Array<number> = [1, 2, 3];

As duas formas são equivalentes. string[] costuma ser mais compacta.

Este array rejeita números:

tags.push(42);

7. Objetos

Tipo escrito diretamente:

const task: {
  id: number;
  title: string;
  completed: boolean;
} = {
  id: 1,
  title: "Estudar",
  completed: false,
};

Interfaces e aliases evitam repetir essa estrutura e serão aprofundados na Aula 3.2.

8. Propriedade opcional

const task: {
  title: string;
  description?: string;
} = {
  title: "Estudar",
};

description? pode estar ausente. Ao acessar, o tipo inclui undefined.

Opcional não significa automaticamente null.

9. Funções

function normalizeTitle(value: string): string {
  return value.trim().replaceAll(/\s+/g, " ");
}
  • value: string: tipo do parâmetro;
  • : string depois dos parênteses: retorno.

TypeScript pode inferir o retorno, mas explicitá-lo em funções públicas ajuda a proteger o contrato.

10. Função que não retorna valor

function showMessage(message: string): void {
  console.log(message);
}

void indica que o valor de retorno não é usado como parte do contrato.

11. Função que nunca termina normalmente

function fail(message: string): never {
  throw new Error(message);
}

never representa um caminho que não produz valor porque lança ou não termina.

12. Parâmetros opcionais e padrão

function greet(name?: string): string {
  return `Olá, ${name ?? "estudante"}!`;
}

Com padrão:

function greet(name = "estudante"): string {
  return `Olá, ${name}!`;
}

13. Tipos em callbacks

const estimates = [1, 2, 3];

const doubled = estimates.map((estimate) => {
  return estimate * 2;
});

O tipo do callback é inferido a partir do array. Isso é tipagem contextual.

14. Erro estático e erro em execução

Erro estático:

const estimate: number = "três";

O analisador pode detectar sem executar.

Erro em execução:

const value = JSON.parse("{ inválido }");

Só aparece quando a operação ocorre.

Alguns problemas podem pertencer às duas categorias dependendo dos tipos e do fluxo.

15. any

let value: any = "texto";
value.nonexistent().anything;

any desativa grande parte da verificação. Pode ser necessário em migrações específicas, mas não deve ser usado para silenciar erros sem compreender a causa.

Trocar todos os erros por any remove justamente a proteção que motivou o TypeScript.

16. unknown

let value: unknown = JSON.parse(text);

unknown aceita qualquer entrada, mas exige verificação antes do uso:

if (typeof value === "string") {
  console.log(value.toUpperCase());
}

Para dados externos, unknown comunica melhor que ainda não confiamos no formato.

17. Assertions

const input = document.querySelector("#title") as HTMLInputElement;

Uma assertion informa ao compilador que o desenvolvedor conhece um tipo mais específico. Ela não verifica o DOM em execução.

Forma mais segura:

const input = document.querySelector("#title");

if (!(input instanceof HTMLInputElement)) {
  throw new Error("Campo title não encontrado.");
}

18. Tipos não alteram o valor

Isto não converte string em número:

const estimate = input.value as unknown as number;

O valor continua sendo string em execução. Converta:

const estimate = Number(input.value);

Depois valide:

if (!Number.isFinite(estimate)) {
  throw new Error("Estimativa inválida.");
}

19. Compilação

Em um projeto com TypeScript instalado:

npx tsc

O compilador:

  1. lê os arquivos e configuração;
  2. analisa tipos;
  3. informa diagnósticos;
  4. quando permitido, emite JavaScript.

O laboratório já contém a fonte .ts e a saída .js correspondente para não depender de instalação externa nesta aula.

20. tsconfig.json

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ES2022",
    "strict": true,
    "rootDir": "src",
    "outDir": "dist"
  },
  "include": ["src/**/*.ts"]
}
  • target: versão aproximada do JavaScript gerado;
  • module: formato de módulos;
  • strict: conjunto de verificações rigorosas;
  • rootDir: fontes;
  • outDir: saída;
  • include: arquivos do projeto.

Configuração será aprofundada na Aula 3.4.

21. strict

Ativar strict desde o início ajuda a evitar um projeto que parece tipado, mas permite muitos valores indefinidos.

Migrações grandes podem exigir etapas. Projetos novos devem preferir configuração estrita.

22. TypeScript não é validação de ambiente de execução

type Task = {
  title: string;
  estimate: number;
};

const response = await fetch("/api/task");
const data = (await response.json()) as Task;

as Task não verifica a resposta. Ele apenas altera a visão do compilador.

Valide:

function isTask(value: unknown): value is Task {
  if (typeof value !== "object" || value === null) {
    return false;
  }

  const candidate = value as Record<string, unknown>;

  return (
    typeof candidate.title === "string" &&
    typeof candidate.estimate === "number"
  );
}

Type guards serão aprofundados na Aula 3.3.

23. Laboratório guiado

Abra o primeiro projeto TypeScript.

Etapa 1 — Compare os arquivos

Observe:

src/app.ts
dist/app.js

Localize anotações que desapareceram na saída.

Etapa 2 — Teste a entrada

O valor de um <input> chega como string. Informe:

  • título válido;
  • título com somente espaços;
  • estimativa numérica;
  • texto em um campo numérico, utilizando o DevTools se necessário.

Etapa 3 — Observe os contratos

O painel apresenta:

  • valor recebido;
  • tipo em ambiente de execução com typeof;
  • valor convertido;
  • objeto final validado.

Etapa 4 — Leia os erros esperados

O arquivo src/type-errors.ts contém exemplos deliberadamente inválidos. Ele serve para leitura e não faz parte da saída executável.

24. Erros comuns

Anotar tudo

Tipagem redundante aumenta ruído. Aproveite inferência quando o tipo é evidente.

Usar any para terminar rápido

O código compila, mas perde proteção.

Acreditar que as converte valores

Assertions não alteram ambiente de execução.

Confiar em JSON porque existe um tipo

Dados externos continuam desconhecidos até validação.

Esperar que o navegador execute .ts

O navegador recebe JavaScript gerado.

Corrigir todos os erros com !

O operador de non-null assertion silencia a possibilidade de ausência sem criar verificação real.

25. Boas práticas

  • mantenha conhecimento sólido de JavaScript;
  • use inferência para valores locais simples;
  • explicite contratos públicos;
  • prefira unknown para entrada externa;
  • evite any;
  • converta valores em ambiente de execução;
  • valide dados externos;
  • habilite strict;
  • separe src e dist;
  • não edite manualmente a saída gerada em projetos reais.

26. Exercícios

Exercício 1 — Primitivas

Tipar nome, carga horária e estado de conclusão.

Exercício 2 — Função

Criar calculateProgress(completed, total): number.

Exercício 3 — Array

Criar um array de títulos e impedir inserção de número.

Exercício 4 — Entrada externa

Receber unknown e confirmar se é string.

Exercício 5 — DOM

Consultar um input e validar com instanceof.

27. Desafio

Migre uma regra do Módulo 2:

  • defina tipos de parâmetros;
  • defina retorno;
  • remova any;
  • crie um exemplo que deve falhar na análise;
  • mantenha validação de ambiente de execução;
  • compare o .ts e o .js.

28. Lista de verificação de conclusão

  • Sei diferenciar TypeScript, JavaScript e framework.
  • Entendo que o navegador executa JavaScript.
  • Sei explicar apagamento de tipos.
  • Uso inferência e anotações conscientemente.
  • Consigo tipar arrays, objetos e funções.
  • Sei por que evitar any.
  • Entendo o papel de unknown.
  • Não uso assertion como validação.
  • Sei ler um tsconfig.json.
  • Valido entrada externa em ambiente de execução.

29. Critérios de avaliação

Critério Pontos
Tipos e inferência corretos 25
Funções tipadas 20
Conversão e validação em ambiente de execução 25
Ausência de any desnecessário 15
Explicação da saída JavaScript 15
Total 100

Resumo

Nesta aula, aprendemos que:

  • TypeScript adiciona análise estática ao JavaScript;
  • o navegador executa o JavaScript gerado;
  • os tipos são apagados;
  • inferência evita anotações redundantes;
  • any desativa proteção e unknown exige verificação;
  • assertions não convertem nem validam valores;
  • entrada externa precisa de validação em ambiente de execução.

Próxima aula

Na Aula 3.2, criaremos contratos reutilizáveis com interfaces, type aliases, propriedades opcionais, readonly e composição de tipos.