Tips & Tricks (Aktualisiert: 3.6.2026)

Claude Code und TypeScript: schneller entwickeln, ohne Typsicherheit zu verlieren

Nutze strict, Zod, Unions, Generics, satisfies und Typ-Tests für bessere Claude-Code-Ergebnisse.

Claude Code und TypeScript: schneller entwickeln, ohne Typsicherheit zu verlieren

Claude Code kann TypeScript-Entwicklung stark beschleunigen, besonders bei Formularen, API-Helfern und Tests. Wenn Typgrenzen unklar sind, entstehen aber genauso schnell fragile Lösungen. Für Einsteiger ist die wichtigste Gewohnheit: erst die Typregeln festlegen, dann die Funktion generieren lassen.

strict bedeutet hier, dass TypeScript verdächtigen Code nicht leicht durchlässt. Domänentypen schreiben Fachregeln als Typen auf. Discriminated Unions modellieren Zustände mit unterschiedlichen Formen, und Laufzeitvalidierung prüft Daten während der Ausführung.

Claude Code zuerst eine Typkarte geben

Vor dem langen Prompt hilft eine kleine Karte: Compiler-Regeln, Domänentypen, externe Eingaben, Zustände und Typ-Tests. Damit wird der generierte Diff leichter überprüfbar.

flowchart TD
  A["Anforderung"] --> B["tsconfig: strict Regeln"]
  B --> C["Domänentypen: Plan und Account"]
  C --> D["Externe Daten: unknown, dann validieren"]
  D --> E["Zustand: Discriminated Unions"]
  E --> F["Typ-Tests: expectTypeOf / tsd"]
  F --> G["Implementierung und Review mit Claude Code"]

Offizielle Referenzen sind strict, noUncheckedIndexedAccess, exactOptionalPropertyTypes, Narrowing, Generics, Utility Types und die Notiz zu satisfies. Für Laufzeitvalidierung ist die Zod-Dokumentation sinnvoll.

Passende interne Artikel: TypeScript Utility Types, TypeScript Generics und Zod Validation.

Mit strict tsconfig beginnen

Sage nicht nur “baue es in TypeScript”. Gib Claude Code zuerst den Compiler-Vertrag.

{
  "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"]
}

Der Prompt sollte die Grenzen nennen.

Dieses Repository nutzt strict TypeScript.
Führe kein any ein. Externe Eingaben als unknown annehmen und mit Zod validieren.
Bei switch über Unions eine never-Prüfung für Vollständigkeit ergänzen.
Nach der Umsetzung npx tsc --noEmit ausführen.

noUncheckedIndexedAccess lässt beim Lesen aus Arrays und Records undefined sichtbar. Das ist strenger, findet aber fehlende API-Felder, leere Listen und unvollständige Übersetzungen früher.

Fall 1: SaaS-Pläne als Domänentypen

Domänentypen sind Fachregeln in TypeScript. Tarife, Rechte, Rechnungsstatus und Veröffentlichungsstatus gehören vor die 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 entfernt Mitglieder aus einer Union. Partial macht Eigenschaften optional. Das passt für Updates, ist aber gefährlich für Create-Inputs, wenn Pflichtfelder verschwinden.

Fall 2: API-Daten von unknown validieren

TypeScript-Typen existieren zur Laufzeit nicht. APIs, Formulare, Cookies, localStorage, CSV und KI-Ausgaben können defekt sein. Nimm sie als unknown an, validiere sie und nutze danach den typisierten Wert.

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 heißt: Der Wert ist noch nicht bewiesen. Anders als any erzwingt es eine Prüfung vor dem Zugriff auf Eigenschaften.

Fall 3: Zahlungsstatus mit einer Union schließen

Zahlungen, Uploads, Formulare und Jobs sind Zustandsmaschinen. status: string ist zu weit.

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;
    }
  }
}

Der never-Zweig sorgt dafür, dass alle gültigen Fälle behandelt werden. Kommt später refunded dazu, verlangt TypeScript den neuen Zweig.

Fall 4: Generics und satisfies

Generics machen Helfer wiederverwendbar, ohne den konkreten Typ am Aufrufort zu verlieren.

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));

Für Konfigurationsobjekte ist satisfies meist besser als eine breite Assertion.

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];
}

Typ-Tests ergänzen

Wichtige öffentliche Typen sollten getestet werden.

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;
  }>();
});

Praxisfälle und Fehler (Use case / Pitfall checklist)

FallWas das Typsystem festlegtWas Claude Code erzeugen kann
SaaS-AbrechnungTarife, Rechnungsstatus, RechteUI-Zweige, Formulare, Texte
Admin-APIZod-Schemas, Antworttypenfetch, Tabellen, Ladezustände
Artikel-CMSslug, Sprache, Publish-Status, BildMDX-Entwürfe, Listen, Validierung
KontaktformularEingabeschema, Ergebnis-UnionUI, Submit-Handler, Tests
FehlerFolgeKorrektur
API-Antwort als anyDefektes JSON kompiliertunknown und Zod
status: stringUnmögliche ZuständeDiscriminated Union
Viele as UserFehler werden verstecktSchema, Guards, satisfies
Partial<T> für CreatePflichtfelder werden optionalcreate und update trennen
Keine Typ-TestsÖffentliche Typen werden breiterexpectTypeOf oder tsd

Bei ClaudeCodeLab erzeugte ein zu breites lang: string einmal ungültige Locale-URLs. Eine geschlossene Union für die Sprachen machte Claude-Code-Änderungen deutlich verlässlicher.

Regeln und 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.

Für Solo-Projekte bietet der Produktkatalog Templates und Checklisten für Claude Code. Für Teams kann Claude Code Training und Beratung strict-Migration, Zod-Grenzen, Typ-Tests und CLAUDE.md-Regeln in einem echten Repository abdecken.

Geprüftes Ergebnis

Ich habe diesen Ablauf in einem kleinen TypeScript-Projekt getestet: API-Antworten von any auf unknown plus Zod umstellen, dann Claude Code Union-Zweige und expectTypeOf-Tests ergänzen lassen. Der konkrete Nutzen war, fehlende Zustände und ungültige Property-Zugriffe vor dem Review zu finden.

#Claude Code #TypeScript #type safety #development efficiency #frontend
Kostenlos

Kostenloses PDF: Claude-Code-Cheatsheet

E-Mail eintragen und eine Seite mit Befehlen, Review-Gewohnheiten und sicheren Workflows herunterladen.

Wir schützen Ihre Daten und senden keinen Spam.

Masa

Über den Autor

Masa

Engineer für praktische Claude-Code-Workflows und Team-Einführung.