# Aula 3.4 - Configuração, lint e formatação

## Identificação

- **Duração:** 2 horas
- **Tipo:** teoria aplicada e laboratório
- **Entrega:** fluxo local de qualidade
- **Laboratório:** [`../exemplos/aula-3.4/index.html`](../exemplos/aula-3.4/index.html)

## Introdução

### O que significa configurar um projeto?

Configurar é registrar decisões para que ferramentas e pessoas trabalhem da mesma
forma. Em vez de cada integrante lembrar quais comandos e regras usar, o projeto
guarda essas decisões em arquivos versionados.

Exemplos:

- `tsconfig.json`: como TypeScript deve verificar e gerar código;
- `eslint.config.js`: quais padrões problemáticos o lint deve apontar;
- `.prettierrc.json`: como o código deve ser formatado;
- `package.json`: quais comandos e versões o projeto utiliza.

### O que é lint?

Lint é uma análise estática do código. Ele procura padrões perigosos ou
inconsistentes sem precisar executar a aplicação.

Uma regra pode alertar sobre:

```ts
const unusedMessage = "não utilizado";
```

ou sobre uma Promise criada sem tratamento. O lint complementa o compilador, mas
não o substitui.

### O que é formatação?

Formatação organiza a aparência do código: espaços, quebras de linha, aspas e
vírgulas. Prettier é um formatter. Ele evita discussões manuais sobre estilo e
produz uma saída previsível.

### ESLint e Prettier são a mesma coisa?

Não:

- **ESLint** analisa padrões e possíveis problemas;
- **Prettier** reorganiza a apresentação do texto.

Algumas regras antigas de lint também cuidavam de espaços e aspas. Em projetos
modernos, é comum deixar a formatação com Prettier e a qualidade lógica com
ESLint.

### TypeScript já não verifica tudo?

Não. Cada ferramenta enxerga uma camada:

| Ferramenta | Pergunta principal |
|---|---|
| TypeScript | Os tipos e contratos são compatíveis? |
| ESLint | O código segue regras de qualidade e evita padrões suspeitos? |
| Prettier | O texto está formatado de maneira consistente? |
| Testes | O comportamento observado corresponde ao esperado? |

Um código pode compilar e ainda falhar em um teste. Também pode estar corretamente
tipado, mas conter uma variável não utilizada.

### Preciso instalar essas ferramentas globalmente?

Não. Prefira dependências de desenvolvimento locais:

```bash
npm install --save-dev typescript eslint prettier
```

Assim, o projeto registra as versões e todos usam a mesma base. Os comandos podem
ser executados por scripts do `package.json`.

### Onde a configuração roda?

Essas ferramentas rodam no ambiente de desenvolvimento, normalmente pelo
terminal, editor ou fluxo de integração contínua. O navegador recebe o
JavaScript gerado; ele não lê `tsconfig.json`, ESLint ou Prettier.

### Como isso entra no nosso projeto?

Vamos criar uma porta única de qualidade:

```bash
npm run quality
```

Ela reunirá verificação de tipos, lint, formatação e testes. Antes de enviar uma
alteração, o desenvolvedor executará o mesmo conjunto que poderá rodar no servidor.

## Objetivos

Ao final da aula, o aluno deverá conseguir:

1. explicar o papel de cada arquivo de configuração;
2. configurar TypeScript em modo estrito;
3. diferenciar compilação e verificação de tipos;
4. entender `include`, `exclude`, `rootDir` e `outDir`;
5. configurar ESLint para TypeScript;
6. diferenciar lint e formatter;
7. configurar Prettier;
8. criar scripts reproduzíveis;
9. entender dependências de desenvolvimento;
10. construir uma sequência de verificação;
11. interpretar falhas por etapa;
12. evitar configurações que escondem erros.

## Pré-requisitos

- Aulas 3.1 a 3.3 concluídas;
- terminal e estrutura de arquivos;
- noções de TypeScript, módulos e testes.

## Pergunta orientadora

> Como transformar decisões de qualidade em verificações automáticas e repetíveis?

## Roteiro sugerido

| Etapa | Duração |
|---|---:|
| Arquivos e dependências | 20 min |
| `tsconfig.json` estrito | 30 min |
| ESLint e Prettier | 30 min |
| Scripts e fluxo | 20 min |
| Laboratório | 15 min |
| Revisão | 5 min |

## 1. Configuração como código

Configuração deve ser:

- legível;
- versionada;
- reproduzível;
- pequena o suficiente para ser entendida;
- alterada com justificativa.

Uma mudança em `tsconfig.json` pode afetar todo o projeto e merece a mesma revisão
que uma mudança em código.

## 2. O papel do `package.json`

Exemplo mínimo:

```json
{
  "name": "painel-typescript",
  "private": true,
  "scripts": {
    "build": "tsc",
    "typecheck": "tsc --noEmit",
    "lint": "eslint .",
    "format": "prettier . --write",
    "format:check": "prettier . --check",
    "test": "node --test"
  }
}
```

`private: true` reduz o risco de publicar o pacote por engano.

## 3. Dependência normal ou de desenvolvimento?

Uma dependência necessária em produção entra em `dependencies`. Ferramentas usadas
para desenvolver, testar ou compilar entram em `devDependencies`.

```bash
npm install express
npm install --save-dev typescript
```

O `package-lock.json` registra a árvore resolvida. Ele deve ser versionado em
aplicações para instalações consistentes.

## 4. Instalação local e `npx`

Scripts do npm encontram executáveis locais automaticamente:

```bash
npm run typecheck
```

Para uma chamada direta:

```bash
npx tsc --noEmit
```

Não confunda `npx` com instalação permanente. Confira o comando e o pacote antes
de permitir downloads.

## 5. Estrutura inicial

```text
painel-typescript/
├── src/
│   └── app.ts
├── tests/
├── eslint.config.js
├── package.json
├── package-lock.json
├── tsconfig.json
└── .prettierrc.json
```

Arquivos gerados, como `dist/`, normalmente não são fontes editadas manualmente.

## 6. `tsconfig.json`

Uma base para aplicação web:

```json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ES2022",
    "moduleResolution": "Bundler",
    "rootDir": "src",
    "outDir": "dist",
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "exactOptionalPropertyTypes": true,
    "noEmitOnError": true
  },
  "include": ["src/**/*.ts"],
  "exclude": ["dist", "node_modules"]
}
```

O conjunto exato depende do ambiente de execução e da ferramenta de compilação. Configuração não é
uma receita universal.

## 7. `target`

`target` define a versão aproximada de JavaScript emitida:

```json
"target": "ES2022"
```

Um target mais antigo pode exigir mais transformações. Compatibilidade com APIs,
como `fetch`, também depende do ambiente e não apenas do target.

## 8. `module` e `moduleResolution`

`module` controla o formato de módulos gerado. `moduleResolution` controla como os
imports são encontrados.

Projetos com bundler e projetos executados diretamente pelo Node podem precisar de
combinações diferentes. Copiar valores sem conhecer o ambiente de execução produz imports que
compilam, mas não executam.

## 9. `rootDir` e `outDir`

```json
"rootDir": "src",
"outDir": "dist"
```

- `rootDir`: raiz das fontes;
- `outDir`: destino do código gerado.

Não importe arquivos de `dist` dentro de `src`. A dependência deve seguir da fonte
para a saída, não voltar da saída para a fonte.

## 10. `include` e `exclude`

`include` escolhe fontes do programa:

```json
"include": ["src/**/*.ts"]
```

`exclude` ajuda a retirar diretórios da descoberta inicial. Ele não é uma barreira
absoluta: um arquivo importado por outro arquivo pode entrar no programa.

Use:

```bash
npx tsc --showConfig
```

para examinar a configuração efetiva.

## 11. Modo estrito

```json
"strict": true
```

Ativa uma família de verificações, incluindo tratamento rigoroso de `null` e
parâmetros de função. É melhor iniciar projetos novos com modo estrito do que
ativá-lo tarde em uma base grande.

## 12. `noUncheckedIndexedAccess`

Sem a opção, o compilador costuma tratar um acesso por índice como se o item
existisse:

```ts
const first = tasks[0];
```

Com ela, o tipo inclui `undefined`. Isso obriga a considerar arrays vazios e chaves
ausentes.

## 13. `exactOptionalPropertyTypes`

Com essa opção:

```ts
interface Task {
  description?: string;
}
```

propriedade ausente e `description: undefined` não são automaticamente a mesma
operação de escrita. O contrato fica mais preciso.

## 14. `noEmitOnError`

```json
"noEmitOnError": true
```

Evita gerar nova saída quando existem erros de compilação. Sem isso, pode surgir a
falsa impressão de que uma compilação com erros foi aprovada.

## 15. Compilação e typecheck

```bash
npm run build
```

Gera arquivos quando configurado.

```bash
npm run typecheck
```

com `tsc --noEmit` apenas verifica os tipos. É útil em editores, hooks e integração
contínua.

## 16. O que o ESLint encontra?

Dependendo das regras:

- variáveis não utilizadas;
- Promises ignoradas;
- condições sempre verdadeiras;
- uso inseguro de `any`;
- imports inconsistentes;
- padrões específicos da equipe.

ESLint não prova que a regra de negócio está correta.

## 17. ESLint com TypeScript

Configuração flat simplificada:

```js
import eslint from "@eslint/js";
import tseslint from "typescript-eslint";

export default tseslint.config(
  eslint.configs.recommended,
  ...tseslint.configs.recommendedTypeChecked,
  {
    languageOptions: {
      parserOptions: {
        projectService: true,
        tsconfigRootDir: import.meta.dirname,
      },
    },
  },
);
```

As versões dos pacotes precisam ser compatíveis. Consulte a documentação da versão
adotada antes de copiar uma configuração.

## 18. Regras com informação de tipos

Algumas regras precisam conhecer o programa TypeScript. Por exemplo, detectar uma
Promise não aguardada exige saber o tipo da expressão.

Essas regras são mais poderosas, mas também custam mais tempo. Separe configurações
quando arquivos JavaScript de ferramentas não fizerem parte do mesmo `tsconfig`.

## 19. Aviso ou erro?

```js
{
  rules: {
    "no-console": "warn",
    "eqeqeq": "error"
  }
}
```

- `off`: regra desativada;
- `warn`: informa, mas normalmente não falha;
- `error`: falha o comando.

Não transforme tudo em aviso apenas para deixar o fluxo verde.

## 20. Correção automática

```bash
npm run lint -- --fix
```

Algumas correções são seguras e automáticas; outras exigem decisão humana. Sempre
revise a alteração gerada.

## 21. Prettier

Configuração pequena:

```json
{
  "semi": true,
  "singleQuote": false,
  "trailingComma": "all",
  "printWidth": 90
}
```

Poucas opções tornam o resultado previsível. O objetivo não é personalizar cada
detalhe, mas reduzir variação.

## 22. Formatar ou apenas conferir?

```bash
prettier . --write
```

altera arquivos.

```bash
prettier . --check
```

somente verifica e retorna falha se houver diferenças. Em CI, prefira `--check`
para não modificar o código no servidor.

## 23. Arquivos ignorados

Use `.prettierignore` e os ignores do ESLint para saídas geradas, cobertura e
dependências:

```text
dist
coverage
node_modules
```

Evite ignorar `src` ou regras difíceis sem investigar a causa.

## 24. Editor não é a fonte da verdade

O editor pode formatar ao salvar, mas nem todos usam o mesmo editor. Os scripts do
projeto são a interface comum:

```bash
npm run lint
npm run format:check
```

Configurações do editor são conveniência; comandos reproduzíveis são o contrato.

## 25. Uma porta de qualidade

No `package.json`:

```json
{
  "scripts": {
    "quality": "npm run typecheck && npm run lint && npm run format:check && npm test"
  }
}
```

O operador `&&` interrompe a sequência na primeira falha. Isso facilita encontrar a
etapa responsável.

## 26. Ordem das etapas

Uma ordem simples:

```text
typecheck → lint → format:check → test → build
```

A ordem pode mudar conforme custo e arquitetura. Verificações rápidas costumam vir
antes das mais demoradas.

## 27. Interpretando uma falha

Leia:

1. qual comando falhou;
2. qual arquivo e linha;
3. qual regra ou diagnóstico;
4. o que a ferramenta esperava;
5. se a correção automática é apropriada.

Não use `as any`, desative a regra ou ignore o arquivo apenas para eliminar a
mensagem.

## 28. Laboratório guiado

Abra o [simulador do fluxo](../exemplos/aula-3.4/index.html).

### Etapa 1 — Execute a análise

Selecione um cenário e pressione **Executar fluxo**. Cada verificador mostrará
seu resultado separadamente.

### Etapa 2 — Observe responsabilidades

O cenário de formatação falha somente no formatter. O código pode continuar
tipado, sem violações de lint e com testes aprovados.

### Etapa 3 — Use correção automática

No cenário apropriado, aplique **Corrigir automaticamente**. Observe que o
formatter altera apresentação, mas não corrige regra de negócio.

### Etapa 4 — Examine os arquivos

Alterne entre `tsconfig.json`, `eslint.config.js`, `.prettierrc.json` e
`package.json`. Relacione cada arquivo à etapa correspondente.

## 29. Fluxo local e CI

O mesmo comando deve funcionar na máquina e no servidor:

```bash
npm ci
npm run quality
```

`npm ci` instala a partir do lockfile e é apropriado para ambientes automatizados.
Ele não substitui a revisão das dependências.

## 30. Erros comuns

### Desativar `strict`

Reduz diagnósticos, mas também reduz a capacidade de encontrar estados ausentes.

### Confundir formatter com corretor de bugs

Prettier reorganiza texto; não valida regra de negócio.

### Usar versões globais

O resultado pode variar entre máquinas.

### Misturar fonte e saída

Editar `dist` cria alterações que serão sobrescritas na próxima compilação.

### Ignorar todos os arquivos difíceis

O fluxo fica verde sem representar qualidade real.

### Executar apenas no final

Falhas acumuladas são mais difíceis de localizar. Rode verificações durante o
desenvolvimento.

## 31. Boas práticas

- versione configurações e lockfile;
- mantenha ferramentas em `devDependencies`;
- habilite TypeScript estrito desde o início;
- separe fonte e saída;
- atribua responsabilidades claras às ferramentas;
- use formatter para estilo e lint para qualidade;
- crie comandos curtos e previsíveis;
- faça o fluxo falhar em violações reais;
- execute localmente antes de compartilhar;
- revise correções automáticas.

## 32. Exercícios

### Exercício 1 — Classificação

Classifique dez problemas entre typecheck, lint, formatação e teste.

### Exercício 2 — `tsconfig`

Ative `strict`, `noUncheckedIndexedAccess` e `noEmitOnError`.

### Exercício 3 — Scripts

Crie `typecheck`, `lint`, `format:check` e `quality`.

### Exercício 4 — Formatação

Formate um arquivo e explique quais mudanças não alteram comportamento.

### Exercício 5 — Diagnóstico

Introduza uma variável não utilizada e identifique qual ferramenta deve sinalizar.

## 33. Desafio

Prepare um projeto que:

- instale ferramentas localmente;
- use TypeScript estrito;
- execute lint com regras tipadas;
- confira formatação sem editar no CI;
- rode testes;
- possua um único comando de qualidade;
- documente como corrigir cada categoria de falha.

## 34. Lista de verificação de conclusão

- [ ] Sei explicar `tsconfig.json`.
- [ ] Diferencio `target`, `module` e resolução de módulos.
- [ ] Entendo `include`, `exclude`, `rootDir` e `outDir`.
- [ ] Uso modo estrito.
- [ ] Diferencio compilação e typecheck.
- [ ] Sei o que ESLint analisa.
- [ ] Sei o que Prettier formata.
- [ ] Diferencio `--write` e `--check`.
- [ ] Uso dependências locais.
- [ ] Consigo executar uma porta única de qualidade.

## 35. Critérios de avaliação

| Critério | Pontos |
|---|---:|
| Configuração TypeScript | 25 |
| Regras de lint | 20 |
| Formatação reproduzível | 15 |
| Scripts do projeto | 20 |
| Interpretação de falhas | 10 |
| Documentação do fluxo | 10 |
| **Total** | **100** |

## Resumo

Nesta aula, aprendemos que:

- configuração registra decisões do projeto;
- TypeScript, ESLint, Prettier e testes têm responsabilidades diferentes;
- modo estrito torna contratos mais precisos;
- dependências locais ajudam a reproduzir resultados;
- `--check` verifica sem alterar;
- scripts fornecem uma interface comum;
- uma porta de qualidade reúne as verificações;
- fluxo verde não deve ser obtido escondendo erros.

## Próxima aula

Na Aula 3.5, veremos Git local, repositórios remotos, branches e pull requests,
separando claramente o que pertence ao Git e o que pertence a plataformas como
GitHub.
