Tips & Tricks (Atualizado: 03/06/2026)

Claude Code e TypeScript: dicas práticas para ganhar velocidade com segurança

Use strict, Zod, Union, genéricos, satisfies e testes de tipos para melhorar TypeScript com Claude Code.

Claude Code e TypeScript: dicas práticas para ganhar velocidade com segurança

Claude Code pode acelerar bastante o desenvolvimento TypeScript, principalmente em formulários, helpers de API e testes. Mas, se as fronteiras de tipo forem vagas, ele também acelera bugs. Para iniciantes, o hábito mais importante é definir as regras de tipo antes de pedir a funcionalidade.

Aqui, strict significa que TypeScript rejeita código suspeito. Tipos de domínio são regras de negócio escritas como tipos. Union discriminada modela estados com formatos diferentes, e validação em runtime confere os dados enquanto o programa roda.

Dê um mapa de tipos primeiro

Antes de um prompt longo, prepare um mapa pequeno: regras do compilador, tipos de domínio, entradas externas, estados e testes de tipo. Esse mapa facilita revisar o diff criado por Claude Code.

flowchart TD
  A["Requisito"] --> B["tsconfig: regras strict"]
  B --> C["Tipos de domínio: Plan e Account"]
  C --> D["Dados externos: unknown e validação"]
  D --> E["Estado: Union discriminadas"]
  E --> F["Testes de tipo: expectTypeOf / tsd"]
  F --> G["Implementação e revisão com Claude Code"]

Use a documentação oficial como base: strict, noUncheckedIndexedAccess, exactOptionalPropertyTypes, Narrowing, Generics, Utility Types e a nota sobre satisfies. Para validação em runtime, veja também a documentação do Zod.

Leituras relacionadas: TypeScript Utility Types, TypeScript Generics e Zod Validation.

Comece com tsconfig strict

Não peça apenas “faça em TypeScript”. Fixe primeiro o contrato do compilador.

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "exactOptionalPropertyTypes": true,
    "noImplicitOverride": true,
    "noFallthroughCasesInSwitch": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src/**/*.ts", "src/**/*.tsx", "tests/**/*.ts"]
}

Inclua as restrições no prompt.

Este repositório usa TypeScript strict.
Não introduza any. Trate entradas externas como unknown e valide com Zod.
Ao lidar com Union em switch, adicione checagem exaustiva com never.
Depois da implementação, rode npx tsc --noEmit.

noUncheckedIndexedAccess mantém undefined visível ao ler arrays e objetos. É mais rigoroso, mas encontra campos ausentes de API, listas vazias e traduções incompletas mais cedo.

Caso 1: modelar planos SaaS

Tipos de domínio colocam regras de negócio no TypeScript. Planos, permissões, estado de cobrança e publicação devem vir antes da UI.

export type Plan = "free" | "pro" | "enterprise";

export type Account = {
  id: string;
  email: string;
  plan: Plan;
  seats: number;
  trialEndsAt: string | null;
};

export type CreateAccountInput = {
  email: string;
  plan: Exclude<Plan, "enterprise">;
  seats?: number;
};

export type UpdateAccountInput = Partial<
  Pick<Account, "email" | "plan" | "seats" | "trialEndsAt">
>;

Exclude remove membros de uma Union. Partial torna propriedades opcionais. É bom para updates, mas perigoso para create input se relaxar campos obrigatórios.

Caso 2: validar API a partir de unknown

Tipos TypeScript somem em runtime. APIs, formulários, cookies, localStorage, CSV e saídas de IA podem vir quebrados. Receba como unknown, valide e só depois use o valor tipado.

npm install zod
import { z } from "zod";

const AccountSchema = z.object({
  id: z.string().min(1),
  email: z.string().email(),
  plan: z.enum(["free", "pro", "enterprise"]),
  seats: z.number().int().positive(),
  trialEndsAt: z.string().datetime().nullable()
});

type Account = z.infer<typeof AccountSchema>;

export function parseAccountResponse(json: unknown): Account {
  return AccountSchema.parse(json);
}

unknown significa que o valor ainda não foi provado. Diferente de any, ele força validação antes de acessar propriedades.

Caso 3: fechar estados de pagamento com Union

Pagamentos, uploads, formulários e jobs são máquinas de estado. status: string é amplo demais.

type PaymentResult =
  | { status: "pending"; invoiceId: string }
  | { status: "paid"; invoiceId: string; paidAt: string }
  | { status: "failed"; invoiceId: string; reason: string };

export function renderPaymentMessage(result: PaymentResult): string {
  switch (result.status) {
    case "pending":
      return `Invoice ${result.invoiceId} is waiting for payment.`;
    case "paid":
      return `Invoice ${result.invoiceId} was paid at ${result.paidAt}.`;
    case "failed":
      return `Invoice ${result.invoiceId} failed: ${result.reason}.`;
    default: {
      const exhaustive: never = result;
      return exhaustive;
    }
  }
}

O ramo never ajuda TypeScript a exigir todos os casos válidos. Se refunded for adicionado depois, o compilador cobra o novo branch.

Caso 4: genéricos e satisfies

Genéricos criam helpers reutilizáveis sem perder o tipo específico da chamada.

export function groupBy<T, K extends PropertyKey>(
  items: readonly T[],
  getKey: (item: T) => K
): Partial<Record<K, T[]>> {
  const grouped: Partial<Record<K, T[]>> = {};

  for (const item of items) {
    const key = getKey(item);
    const bucket = grouped[key] ?? [];
    bucket.push(item);
    grouped[key] = bucket;
  }

  return grouped;
}

const accounts = [
  { id: "a1", plan: "free" },
  { id: "a2", plan: "pro" },
  { id: "a3", plan: "pro" }
] as const;

const byPlan = groupBy(accounts, (account) => account.plan);
const proAccounts = byPlan.pro ?? [];

console.log(proAccounts.map((account) => account.id));

Em objetos de configuração, prefira satisfies a uma asserção ampla.

type ApiRoute = {
  method: "GET" | "POST" | "PATCH" | "DELETE";
  path: `/${string}`;
  auth: boolean;
};

const routes = {
  listAccounts: { method: "GET", path: "/accounts", auth: true },
  createAccount: { method: "POST", path: "/accounts", auth: true },
  healthCheck: { method: "GET", path: "/health", auth: false }
} as const satisfies Record<string, ApiRoute>;

type RouteName = keyof typeof routes;

export function getRoute(name: RouteName) {
  return routes[name];
}

Adicione testes de tipo

Tipos públicos importantes também precisam de teste.

npm install -D vitest tsd
import { expectTypeOf, test } from "vitest";

type CreateAccountInput = {
  email: string;
  plan: "free" | "pro";
  seats?: number;
};

test("CreateAccountInput keeps the public API narrow", () => {
  expectTypeOf<CreateAccountInput>().toMatchTypeOf<{
    email: string;
    plan: "free" | "pro";
    seats?: number;
  }>();
});

Usos reais e armadilhas (Use case / Pitfall checklist)

Caso de usoO que os tipos fixamO que Claude Code gera
Cobrança SaaSplanos, faturas, permissõesUI, formulários, mensagens
Admin com APIschemas Zod, respostasfetch, tabelas, loading
CMS de artigosslug, idioma, publicação, imagemrascunhos MDX, listagens, validação
Formulário contatoschema de entrada, Union de resultadoUI, envio, testes
ArmadilhaEfeitoCorreção
Resposta API como anyJSON quebrado compilaunknown e Zod
status: stringestados impossíveisUnion discriminada
Muitos as Usererros escondidosschema, guards, satisfies
Partial<T> no createcampos obrigatórios viram opcionaisseparar create e update
Sem testes de tipotipos públicos alargamexpectTypeOf ou tsd

No fluxo de artigos da ClaudeCodeLab, Masa já viu URLs de locale inválido porque lang era apenas string. Ao fechar o locale em uma Union, as sugestões de Claude Code ficaram bem mais previsíveis.

Regras e CTA

## TypeScript rules
- Use strict TypeScript.
- Do not introduce `any`. Use `unknown` at external boundaries.
- Prefer discriminated unions for states.
- Prefer `satisfies` over broad type assertions.
- Derive API types from Zod schemas when runtime data is involved.
- Add Vitest or tsd style type checks for exported helper types.
- Run `npx tsc --noEmit` before reporting completion.

Para projetos solo, o catálogo de produtos reúne templates e checklists para Claude Code. Para equipes, o treinamento e consultoria Claude Code pode cobrir migração strict, fronteiras Zod, testes de tipo e regras de CLAUDE.md em um repositório real.

Resultado testado

Testei este fluxo em um projeto TypeScript pequeno: troquei respostas API de any para unknown com Zod e pedi ao Claude Code que adicionasse branches Union e testes expectTypeOf. O ganho concreto foi encontrar estados não tratados e acessos a propriedades inexistentes antes da revisão.

#Claude Code #TypeScript #type safety #development efficiency #frontend
Grátis

PDF grátis: cheatsheet do Claude Code

Informe seu e-mail e baixe uma página com comandos, hábitos de revisão e workflows seguros.

Cuidamos dos seus dados e não enviamos spam.

Masa

Sobre o autor

Masa

Engenheiro focado em workflows práticos com Claude Code.