1
Typescript
ScriptSorcerer edited this page 2026-09-23 20:53:32 +02:00
This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

TypeScript

Dieses Projekt wird schrittweise von JavaScript nach TypeScript migriert. JS- und TS-Dateien existieren nebeneinander und können sich gegenseitig importieren.

Voraussetzungen

  • Node.js ≥ 22.18 (oder ≥ 23.6), lokal und im Dockerfile. Node führt .ts-Dateien direkt aus, indem es die Typannotationen entfernt („Type Stripping“). Es gibt keinen Build-Schritt.
  • typescript und @types/node als Dev-Dependencies.

Beim Start kann je nach Node-Version eine ExperimentalWarning zum Type Stripping erscheinen. Diese ist harmlos.

Commands

Command Zweck
npx tsc Prüft das ganze Projekt auf Typfehler (erzeugt keine Dateien)
npx tsc -p tsconfig.check.json Prüft nur die in dieser Config angegebenen Dateien
node server.js Startet die App wie bisher, .ts-Dateien werden automatisch geladen
node --version Prüfen, ob die Node-Version Type Stripping unterstützt

Achtung: npx tsc datei.ts ignoriert die tsconfig.json (also auch strict). Für einzelne Dateien stattdessen eine separate Config verwenden:

{
  "extends": "./tsconfig.json",
  "include": ["src/config.ts"]
}

tsconfig.json

{
  "compilerOptions": {
    "target": "ES2022",
    "lib": ["ES2022"],
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "allowJs": true,
    "checkJs": false,
    "noEmit": true,
    "strict": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "types": ["node"],
    "allowImportingTsExtensions": true,
    "erasableSyntaxOnly": true,
    "verbatimModuleSyntax": true
  },
  "include": ["**/*.js", "**/*.ts"],
  "exclude": ["node_modules", "public"]
}

Wichtige Optionen

  • noEmit: TypeScript prüft nur, es erzeugt keine .js-Dateien.
  • allowJs: JS-Dateien dürfen TS-Dateien importieren und umgekehrt.
  • checkJs: false: JS-Dateien werden nicht geprüft. Sonst entstehen tausende Fehler, weil JS-Code keine Typinformationen hat.
  • strict: Strenge Prüfung für alle .ts-Dateien (u. a. keine impliziten any, Null-Checks).
  • allowImportingTsExtensions: Erlaubt Imports mit .ts-Endung (nötig für Node).
  • erasableSyntaxOnly: Verbietet TS-Features, die Node nicht einfach entfernen kann (siehe unten).
  • verbatimModuleSyntax: Reine Typ-Imports müssen mit import type markiert werden.

Regeln für TS-Dateien

Imports immer mit Dateiendung

// richtig
import { createConfig } from "./config.ts";

// falsch – Node findet die Datei nicht
import { createConfig } from "./config.js";
import { createConfig } from "./config";

Typ-Imports kennzeichnen

import type { Config } from "./config.ts";

Erlaubt / nicht erlaubt

Erlaubt sind Typannotationen, interface, type, Generics und as-Casts.

Nicht erlaubt (funktioniert nicht mit Type Stripping): enum, namespace, Parameter Properties im Konstruktor (constructor(private x: string)). Stattdessen Union Types bzw. normale Klassenfelder verwenden.

unknown statt any

any schaltet die Typprüfung ab. Für Werte unbekannten Typs unknown verwenden, dann erzwingt TypeScript eine Prüfung oder Umwandlung (z. B. String(value)).

Dokumentation mit TSDoc

/**
 * Wandelt einen Wert in eine Ganzzahl um.
 *
 * @param value - Der umzuwandelnde Wert.
 * @param fallback - Rückgabewert, falls das Parsen fehlschlägt.
 * @returns Die Ganzzahl oder `fallback`.
 */

Bei @param keine Typen in {} angeben, die stehen bereits in der Signatur.

Einzelne JS-Dateien prüfen

Soll eine JS-Datei trotz checkJs: false geprüft werden, ganz oben einfügen:

// @ts-check

Migrationsstrategie

  1. Eine Datei nach der anderen migrieren, beginnend mit Dateien, die wenig andere Dateien importieren.
  2. .js in .ts umbenennen, Typen ergänzen, alte Datei löschen.
  3. Alle Imports der Datei auf die .ts-Endung anpassen.
  4. npx tsc ausführen, bis keine Fehler mehr kommen.
  5. Tests laufen lassen.

Große Dateien (repositories.js, chatService.js) sowie Tests und Frontend-Code (public/js) vorerst in JS belassen.

Bereits migriert

src/config.ts

  • Exportiert das Interface Config und den Typ TrustProxyValue.
  • createConfig(overrides: Partial<Config>): Partial macht alle Felder optional, es müssen nur die zu überschreibenden Werte angegeben werden.
  • Umbenennung: modelRequestYTimeoutMs → modelRequestTimeoutMs (Tippfehler im alten Code).