Refactoring von Legacy-Code in TypeScript: Eine Schritt-für-Schritt-Anleitung
Die Arbeit mit Legacy-Code ist ein unvermeidlicher Teil des Lebens eines jeden Entwicklers, insbesondere in großen Projekten. Oft ist dieser Code in JavaScript ohne strenge Typisierung geschrieben, strotzt vor "magischen" Strings, unklaren Funktionen und fehlender Modularität. Der Wechsel zu TypeScript ist nicht nur eine Änderung der Syntax, sondern eine Möglichkeit, die Architektur, Lesbarkeit und Wartbarkeit des Projekts erheblich zu verbessern. In diesem Artikel werden wir eine bewährte Strategie für das Refactoring von Legacy-Code in TypeScript durchgehen, die Risiken minimiert und maximalen Nutzen bringt.
Warum ist TypeScript ideal für das Refactoring von Legacy-Code?
TypeScript bietet einzigartige Möglichkeiten für sicheres Refactoring:
- Statische Typisierung: Ermöglicht es, Fehler bereits zur Kompilierzeit zu erkennen, anstatt zur Laufzeit.
- Automatische Dokumentation: Typen dienen als lebendige Dokumentation, die erklärt, welche Daten eine Funktion erwartet.
- Verbesserte Navigation und Autovervollständigung: Die IDE (VS Code, WebStorm) versteht die Code-Struktur, was die Entwicklung beschleunigt.
- Sichere Refactorings: Das Umbenennen von Variablen oder Ändern von Funktionssignaturen erfolgt mit der Gewissheit, dass nichts kaputt geht.
- Sukzessive Einführung: TypeScript kann Datei für Datei zum Projekt hinzugefügt werden, ohne alles auf einmal umschreiben zu müssen.
Schritt 1: Vorbereitung und Einrichtung der Umgebung
Bevor Sie den Code anfassen, müssen Sie die Infrastruktur vorbereiten. Ohne sie wird das Refactoring zum Chaos.
- Stellen Sie sicher, dass Sie Tests haben. Dies ist die wichtigste Regel des Refactorings. Wenn es keine Tests gibt, schreiben Sie zumindest Integrationstests für die Schlüsselmodule. Ohne Tests riskieren Sie, funktionierende Funktionalität zu zerstören.
- Richten Sie TypeScript ein. Installieren Sie
typescriptund erstellen Sie einetsconfig.json. - Aktivieren Sie strenge Prüfungen. Fügen Sie in der
tsconfig.jsonunbedingt"strict": truehinzu. Dies aktiviertstrictNullChecks,noImplicitAnyund andere nützliche Optionen.
Beispiel einer minimalen tsconfig.json:
{ "compilerOptions": { "target": "ES2020", "module": "commonjs", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "outDir": "./dist" }, "include": ["src/**/*"]}- Richten Sie Linter und Formatierer ein. ESLint mit dem Plugin für TypeScript (
@typescript-eslint) und Prettier helfen, einen einheitlichen Codestil beizubehalten.
Schritt 2: Schrittweise Migration von JavaScript zu TypeScript
Versuchen Sie nicht, das gesamte Projekt an einem Tag umzuschreiben. Verwenden Sie die Strategie "Datei für Datei".
Vorgehensweise:
- Benennen Sie die Datei
legacyModule.jsinlegacyModule.tsum. - Fügen Sie Typen für exportierte und importierte Funktionen hinzu.
- Verwenden Sie vorübergehend
any, wenn Sie sich beim Typ nicht sicher sind. Markieren Sie solche Stellen mit einem Kommentar// TODO: fix type. - Führen Sie die Tests aus und überprüfen Sie, ob alles funktioniert.
Beispiel: Angenommen, wir haben eine Legacy-Funktion in JavaScript:
// oldModule.jsfunction calculateDiscount(price, customerType) { if (customerType === 'vip') { return price * 0.8; } return price * 0.95;}Nach dem Refactoring in TypeScript:
// oldModule.tstype CustomerType = 'regular' | 'vip';
function calculateDiscount(price: number, customerType: CustomerType): number { if (customerType === 'vip') { return price * 0.8; } return price * 0.95;}Der Typ CustomerType macht den Code selbstdokumentierend