TypeScript lernen 2026: Der ehrliche Lernpfad mit echten Zeitangaben

TypeScript lernen 2026: Der ehrliche Lernpfad mit echten Zeitangaben

TypeScript lernen heißt in der Praxis: JavaScript weiterschreiben, aber dem Compiler vorher sagen, welche Form die Daten haben. Das ist die ganze Idee. Alles andere — Generics, Utility Types, satisfies, Conditional Types — ist Ausbau, nicht Fundament.

Dieser Artikel ist bewusst anders aufgebaut als die meisten Tutorials. Wir verkaufen Ihnen keinen „In 7 Tagen zum TypeScript-Profi”-Fahrplan, weil dieser Fahrplan nicht existiert. Stattdessen bekommen Sie einen Lernpfad mit ehrlichen Zeitangaben, die tatsächlichen Fehlermeldungen des Compilers im Wortlaut und Zahlen, die wir auf unserem eigenen Server gemessen haben.

Messstand dieses Artikels: 4. August 2026

Alle Versions- und Zeitangaben stammen von diesem Tag und wurden live abgefragt, nicht aus dem Gedächtnis zitiert. Das ist bei diesem Thema besonders wichtig, denn TypeScript hat gerade den größten Umbau seiner Geschichte hinter sich — und ein großer Teil der Tutorials im Netz beschreibt eine Welt, die es so nicht mehr gibt.

Der Stand, den wir gemessen haben:

WasWertWie geprüft
Aktuelle stabile Version7.0.2npm view typescript dist-tags
Veröffentlicht am8. Juli 2026npm view typescript time --json
Vorgänger-Generation6.0.3 (16. April 2026)dito
Release Candidate für 77.0.1-rc (18. Juni 2026)dito
Repository des neuen Compilersmicrosoft/typescript-go, 26.136 SterneGitHub-API
Klassisches Repositorymicrosoft/TypeScript, 110.061 Sterne, letztes Release-Tag: v6.0.3GitHub-API

Prüfen Sie das selbst nach, es dauert fünf Sekunden:

npm view typescript dist-tags
npm view typescript version

Wenn dort etwas anderes steht als 7.0.2, ist dieser Artikel an dieser Stelle veraltet — und Sie haben in derselben Sekunde die richtige Antwort.

Die kurze Version für Eilige

  • TypeScript ist JavaScript plus Typen. Jede gültige .js-Datei ist bereits gültiges TypeScript. Sie fangen nicht bei null an.
  • Zur Laufzeit existiert TypeScript nicht. Die Typen werden vor der Ausführung entfernt. Sie sind eine Prüfung beim Schreiben, kein Schutz zur Laufzeit.
  • Realistische Zeit bis produktiv: rund 8 bis 15 Stunden für JS-Entwickler bis zum ersten sinnvollen Einsatz, 3 bis 6 Monate bis zur Souveränität. Wer bei null anfängt, sollte zuerst JavaScript lernen.
  • TypeScript 7 ist ein kompletter Neubau in Go. Wir haben gemessen: bei 1.500 Dateien 0,62 s statt 2,34 s — Faktor 3,8 in unserem Test, und 40 % weniger Speicher.
  • Das npm-Paket enthält keine JavaScript-Bibliothek mehr, sondern eine native Binärdatei. Für Lernende irrelevant, für Tool-Autoren ein Bruch.
  • tsc --init erzeugt heute strengere Voreinstellungen als früher — normaler Anfängercode schlägt damit sofort fehl. Wir zeigen genau, warum das gut ist und was Sie sehen werden.
  • Der ehrliche Teil: Es gibt Projekte, bei denen TypeScript sich nicht lohnt. Welche das sind, steht weiter unten ungeschönt.
🧪

Direkt mitmachen, ohne etwas zu installieren Jedes Beispiel aus diesem Artikel können Sie in unserem TypeScript Playground sofort ausprobieren: Code links, Typfehler und fertiges JavaScript rechts. Läuft komplett in Ihrem Browser.

Aufsteigende Treppe aus fünf leuchtenden Plattformen mit Meilenstein-Fähnchen und einer Uhr, die zunehmende Lernzeit symbolisiert

Für wen ist dieser Artikel — und für wen nicht?

Wir sprechen zwei Gruppen an, die unterschiedliche Probleme haben. Damit Sie nicht das Falsche lesen, hier die klare Trennung.

Gruppe A: Sie können JavaScript und wollen umsteigen

Sie schreiben seit Monaten oder Jahren JS, kennen map, async/await, Module und Promises. Ihr Problem ist nicht das Programmieren, sondern eine neue Notationsebene: Sie müssen lernen, über die Form Ihrer Daten zu sprechen, statt nur über deren Verarbeitung.

Für Sie ist der Einstieg erfreulich kurz. Sie können die Abschnitte „Was ist ein Typ überhaupt” überspringen und direkt bei „Die sechs Konzepte, die 90 % abdecken” einsteigen. Realistisch sind Sie nach einem konzentrierten Wochenende produktiv — nicht souverän, aber produktiv.

Gruppe B: Sie sind echter Einsteiger

Sie haben wenig oder gar nicht programmiert und hören überall, TypeScript sei „der Standard”. Das stimmt sogar. Trotzdem ein unbequemer Rat:

Lernen Sie zuerst JavaScript. Mindestens die Grundlagen.

Der Grund ist nicht Prinzipienreiterei, sondern Fehlerdiagnose. Wenn Sie TypeScript lernen, ohne JavaScript zu können, bekommen Sie Fehlermeldungen, die zwei Probleme gleichzeitig beschreiben: einen Denkfehler in Ihrem Programm und eine Typverletzung. Sie können die beiden nicht auseinanderhalten, weil Ihnen der Vergleichsmaßstab fehlt. Das ist der häufigste Grund, warum Einsteiger TypeScript als „feindselig” erleben.

Ein tragfähiger Weg für Gruppe B:

  1. JavaScript-Grundlagen — Variablen, Funktionen, Arrays, Objekte, Schleifen, fetch. Rund 40 bis 80 Stunden, verteilt über einige Wochen.
  2. Ein kleines Projekt in reinem JS fertigstellen. Nicht überspringen. Sie brauchen die Erfahrung, dass Code auch ohne Typen funktioniert — sonst verstehen Sie nie, was Typen eigentlich hinzufügen.
  3. Dann dieser Artikel, von vorne.

Wer Schritt 1 und 2 auslässt, kämpft später doppelt. Wir haben das oft genug gesehen, um es deutlich zu schreiben.

Was TypeScript wirklich ist (und was es nicht ist)

TypeScript ist eine Obermenge von JavaScript. Konkret: Sie benennen app.js in app.ts um, und die Datei ist gültiges TypeScript. Nichts kaputt, nichts umzuschreiben. Sie können dann anfangen, Typen zu ergänzen — Datei für Datei, Zeile für Zeile.

Der zweite Punkt ist der, den Anfänger am häufigsten missverstehen:

Zur Laufzeit gibt es keine Typen. Der Compiler prüft Ihren Code und wirft die Typannotationen dann weg. Was am Ende läuft, ist gewöhnliches JavaScript. Das hat eine unmittelbare Konsequenz:

function verarbeite(daten: string) {
  return daten.toUpperCase();
}

// Kompiliert einwandfrei — der Compiler kennt den Typ.
verarbeite("hallo");

// Kommt diese Zahl zur Laufzeit aus einer API,
// hat der Compiler sie nie gesehen. Es knallt trotzdem.
const ausApi: any = 42;
verarbeite(ausApi);

TypeScript schützt Sie beim Schreiben, nicht beim Ausführen. Daten von außen — API-Antworten, Formulareingaben, JSON.parse, localStorage — sind für den Compiler ein blinder Fleck. Wer das früh versteht, spart sich eine ganze Klasse von Enttäuschungen. Wie man diese Grenze absichert, steht weiter unten im Abschnitt über unknown.

Node führt TypeScript inzwischen direkt aus — aber es prüft nichts

Das ist neu und stiftet gerade viel Verwirrung. Wir haben es auf Node v22.23.0 gemessen:

$ node hello.ts
node ran TS directly: 5

Das funktioniert. Node entfernt die Typen und führt den Rest aus. Nun der entscheidende Teil — dieselbe Ausführung mit einem offensichtlichen Typfehler:

const x: number = "keine Zahl";
console.log("Node hat NICHT gemeckert:", x);
$ node nativebad.ts
Node hat NICHT gemeckert: keine Zahl

Node hat den Fehler nicht bemerkt, weil Node gar nicht prüft. Es entfernt Typen (type stripping), mehr nicht. Die Prüfung macht ausschließlich tsc. Wer glaubt, node datei.ts sei „TypeScript ausführen”, hat die Typsicherheit stillschweigend abgeschaltet und merkt es nicht — der gefährlichste Zustand überhaupt, weil alles grün aussieht.

Eine zweite Einschränkung fanden wir im selben Test. Manche TypeScript-Konstrukte lassen sich nicht einfach wegstreichen:

$ node enum.ts
SyntaxError [ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX]: TypeScript enum is not supported in strip-only mode

enum erzeugt echten Laufzeit-Code und ist deshalb im Strip-Modus verboten. Genau dafür gibt es die Compiler-Option erasableSyntaxOnly, die solche Konstrukte schon beim Prüfen verbietet:

$ tsc --erasableSyntaxOnly enum.ts
enum.ts(1,6): error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.

Praktische Regel: Wenn Sie node datei.ts nutzen wollen, schalten Sie erasableSyntaxOnly ein und verzichten Sie auf enum (nutzen Sie stattdessen Union-Typen aus Zeichenketten — dazu unten mehr). Und lassen Sie tsc --noEmit trotzdem laufen. Node ersetzt den Compiler nicht, es ersetzt nur den Build-Schritt.

TypeScript 7: Warum Ihre Tutorials gerade veralten

Am 8. Juli 2026 erschien TypeScript 7.0.2 als stabile Version. Das ist keine gewöhnliche Hauptversion, sondern ein vollständiger Neubau des Compilers in der Sprache Go. Der bisherige Compiler war selbst in TypeScript geschrieben und lief auf Node.

Für Lernende ist das zunächst eine gute Nachricht und ansonsten unsichtbar: Die Sprache ist dieselbe, Ihre Typen sehen genauso aus, tsc heißt weiter tsc. Aber es gibt Details, die Sie kennen sollten, weil sie erklären, warum manche Anleitung nicht mehr passt.

Was wir selbst gemessen haben

Wir haben beide Versionen auf derselben Maschine installiert (AMD EPYC, 12 Kerne) und identischen Code kompilieren lassen. Der Testcode war generiert: Module mit Interfaces, Mapped Types, keyof, Map, und einer Importkette, in der jedes Modul das vorherige benutzt — also echte Abhängigkeitsarbeit für den Typprüfer, kein triviales Nebeneinander.

Ergebnis, jeweils der Median aus drei Läufen mit --noEmit --strict:

UmfangTypeScript 6.0.3TypeScript 7.0.2Faktor
1 Datei (4 Zeilen)1,06 s0,28 s3,8×
300 Dateien (~9.000 Zeilen)1,41 s0,50 s2,8×
1.500 Dateien (~30.000 Zeilen)2,34 s0,62 s3,8×

Und der Speicherbedarf beim größten Lauf, gemessen als maximaler Arbeitsspeicher des Prozesses:

TypeScript 6.0.3TypeScript 7.0.2
1.500 Dateien316 MB192 MB

Zwei Beobachtungen, die uns überrascht haben, und die wir wichtiger finden als die reine Faktor-Zahl:

Erstens: Der Sprung ist beim kleinsten Projekt prozentual genauso groß wie beim größten. Der Vorteil liegt also nicht nur in der Skalierung, sondern zu einem erheblichen Teil im Startvorgang. TypeScript 6 muss erst 8,9 MB JavaScript laden und von Node übersetzen lassen, bevor es überhaupt Ihre erste Zeile ansieht. Für den Alltag ist das die wichtigere Zahl: Nicht der Riesen-Build wird schneller, sondern die hundert kleinen Prüfläufe pro Tag.

Zweitens: Von 300 auf 1.500 Dateien — also die fünffache Menge — stieg TypeScript 7 nur von 0,50 s auf 0,62 s. Auch hier dominiert der feste Grundaufwand. Wir würden aus unseren Zahlen deshalb nicht ableiten, dass jedes reale Projekt exakt 3,8-mal schneller wird. Generierter Code mit einfachen Typen ist gutmütig; echte Projekte mit tiefen Generics, umfangreichen node_modules und komplexen Bibliothekstypen belasten den Prüfer anders. Wir berichten, was wir gemessen haben, nicht was wir gern hochrechnen würden.

Zwei Tacho-Anzeigen nebeneinander mit deutlich unterschiedlichen Zeigerständen, daneben Dateisymbole die durch einen Trichter fließen

Das npm-Paket enthält keine JavaScript-Bibliothek mehr

Das ist der Bruch, den man beim Lernen nicht merkt und beim Werkzeugbau sofort. Wir haben in beide Pakete hineingeschaut:

# TypeScript 6.0.3
$ ls -la node_modules/typescript/lib/typescript.js
-rw-r--r-- 1 root root 9144216   node_modules/typescript/lib/typescript.js   # 8,9 MB

# TypeScript 7.0.2
$ ls node_modules/typescript/lib/typescript.js
ls: cannot access '...': No such file or directory

Die Datei existiert schlicht nicht mehr. Stattdessen zieht das Paket eine plattformspezifische Binärdatei nach:

$ du -sh node_modules/@typescript/typescript-linux-x64
27M     node_modules/@typescript/typescript-linux-x64

$ file node_modules/@typescript/typescript-linux-x64/lib/tsc
ELF 64-bit LSB executable, x86-64, statically linked, Go BuildID=..., stripped

Ein statisch gelinktes Go-Programm. Das Paket typescript selbst deklariert zwanzig solcher Plattformpakete als optionale Abhängigkeiten — npm lädt genau das für Ihr System passende.

Die Folge für Programme, die den Compiler als Bibliothek benutzen:

# TypeScript 6.0.3
$ node -e "const ts=require('typescript'); console.log(ts.version, typeof ts.createProgram)"
6.0.3 function

# TypeScript 7.0.2
$ node -e "const ts=require('typescript'); console.log(ts.version, typeof ts.createProgram)"
7.0.2 undefined

require('typescript') liefert unter Version 7 nur noch version und versionMajorMinor — sonst nichts. Die alte Compiler-API ist aus dem Hauptexport verschwunden. Es gibt einen Nachfolger, und der trägt seinen Reifegrad im Namen:

$ node -e "import('typescript/unstable/sync').then(a=>console.log(Object.keys(a).length,'Exporte'))"
43 Exporte

Die Pfade heißen typescript/unstable/sync, typescript/unstable/ast, typescript/unstable/async und so weiter. „unstable” ist hier eine Ansage, keine Koketterie.

Was heißt das für Sie als Lernenden? Wenn Sie TypeScript nur benutzen, gar nichts — schreiben Sie Ihren Code, alles funktioniert. Relevant wird es, wenn ein Werkzeug in Ihrer Werkzeugkette den Compiler intern anspricht: ältere ESLint-Aufsätze, Dokumentationsgeneratoren, Bundler-Plugins, Code-Modifikationswerkzeuge. Wenn nach einem Wechsel auf Version 7 ein Werkzeug mit einer merkwürdigen Meldung aussteigt, ist das fast immer die Ursache. Der ruhige Weg für Bestandsprojekte: bei 6.0.3 bleiben, bis die eigene Werkzeugkette nachgezogen hat. Für ein neues Lernprojekt gibt es keinen Grund, nicht sofort Version 7 zu nehmen.

Ein Fehler, in den wir prompt selbst gelaufen sind

Beim ersten Versuch, einzelne Testdateien zu prüfen, bekamen wir für jede Datei nur das hier:

$ tsc --noEmit --strict errs/e1.ts
error TS5112: tsconfig.json is present but will not be loaded if files are specified
on commandline. Use '--ignoreConfig' to skip this error.

Keine Typprüfung, nur diese Beschwerde. Der Grund ist eigentlich alt: Wenn Sie tsc Dateinamen direkt übergeben, wird die tsconfig.json ignoriert — das war schon immer so, nur schwieg der Compiler früher dazu. Jetzt sagt er es laut und verweigert die Arbeit, bis man sich entscheidet.

Der Kuriositätswert: Wir haben zur Kontrolle dasselbe mit 6.0.3 laufen lassen und exakt dieselbe Meldung bekommen. Der Fehlercode existiert also schon in der Vorgänger-Generation — wir hatten ihn nur nie gesehen, weil wir tsc sonst nie mit Dateinamen aufrufen. Was uns eine hübsche Lehre gab: Wir hätten das fast als Neuerung von Version 7 in diesen Artikel geschrieben. Ein Verhalten, das einem zum ersten Mal begegnet, ist nicht dasselbe wie ein neues Verhalten. Die Gegenprobe mit der alten Version kostete zwanzig Sekunden und hat eine falsche Behauptung verhindert.

Die praktische Lehre für Sie: Rufen Sie tsc ohne Dateinamen auf. Es findet die tsconfig.json selbst und prüft das gesamte Projekt so, wie Ihr Editor es auch tut. Einzeldateien auf der Kommandozeile sind fast immer ein Zeichen dafür, dass etwas anderes schiefläuft.

Und ein echter Fehlschlag: tsc --watch reagierte bei uns nicht

Dies ist der Teil, den wir am liebsten weggelassen hätten — und deshalb der wertvollste. Der Watch-Modus soll bei jeder Dateiänderung neu prüfen. Bei uns tat er das nicht.

Der Ablauf: tsc --watch starten, Datei mit einem eindeutigen Fehler verändern, warten. Ergebnis:

10:00:31 - Starting compilation in watch mode...
10:00:32 - Found 0 errors. Watching for file changes.
[Datei geändert — dann acht Sekunden Stille. Nichts.]

Bevor wir daraus eine Aussage über TypeScript machen, haben wir gegengeprüft — im selben Verzeichnis, derselben Maschine, derselben Minute, nur mit Version 6.0.3:

10:00:52 - Starting compilation in watch mode...
10:00:53 - Found 0 errors. Watching for file changes.
10:00:58 - File change detected. Starting incremental compilation...
src/a.ts(1,14): error TS2322: Type 'string' is not assignable to type 'number'.
10:00:58 - Found 1 error. Watching for file changes.

Version 6 bemerkt die Änderung nach fünf Sekunden. Version 7 bemerkte sie gar nicht. Damit war klar: Es liegt nicht an unserem Testaufbau, unserem Editor oder unserer Geduld.

Wir sind dann eine Ebene tiefer gegangen und haben die Systemaufrufe mitgeschnitten. Das Ergebnis war eindeutig — und anders, als wir vermutet hatten:

$ strace -f -e trace=fanotify_mark ... tsc --watch
# Alle überwachten Verzeichnisse:
"/tmp/wfinal/node_modules/@typescript/typescript-linux-x64/lib"

Das Quellverzeichnis src/ wurde kein einziges Mal registriert. Überwacht wurde ausschließlich das Bibliotheksverzeichnis des Compilers selbst. Alle vier Registrierungsaufrufe meldeten Erfolg — es lag also nicht an fehlenden Rechten oder einem Dateisystem, das die Schnittstelle nicht unterstützt. Der Compiler hat schlicht nie darum gebeten, unseren Quellcode zu beobachten.

Ein Detail passt dazu und erklärt, warum wir das Problem zwischendurch fast „wegdiskutiert” hätten: Bei einem unserer Zwischentests schlug der Watch-Modus doch an — nämlich als eine neue Datei ins Verzeichnis kam. Änderungen an bestehenden Dateien blieben unbemerkt, das Anlegen einer neuen Datei nicht. Genau solche Teilerfolge sind heimtückisch: Hätten wir nur diesen einen Test gemacht, stünde hier jetzt „funktioniert”.

Ein Blick in die Fehlerdatenbank des Projekts zeigte, dass wir nicht allein sind: Issue #4795, „tsc --watch doesn’t recompile on file change”, geöffnet am 30. Juli 2026, offen zum Zeitpunkt unserer Messung. Der Melder beschreibt exakt unsere Beobachtung inklusive des Vergleichs 6.0.3 funktioniert / 7.0.2 nicht. Es existiert außerdem ein Korrekturvorschlag (#4661), der ein verwandtes Problem in Docker-Umgebungen behebt — der beschreibt allerdings fehlschlagende Registrierungsaufrufe, und genau die hatten wir nicht. Unser Fall liegt auf einer gewöhnlichen ext4-Partition in einer KVM-Maschine, nicht in Docker.

Was Sie daraus mitnehmen sollten: Wenn Ihr tsc --watch unter Version 7 stumm bleibt, liegt es nicht an Ihnen. Prüfen Sie es gezielt, bevor Sie sich darauf verlassen — bauen Sie absichtlich einen Fehler ein und schauen Sie, ob er gemeldet wird. Bis das behoben ist, funktionieren als Ersatz: die Fehleranzeige Ihres Editors (die läuft über den Sprachserver und war bei uns unbeeindruckt), ein tsc --noEmit vor jedem Commit, oder schlicht Version 6.0.3 für den Entwicklungsalltag.

Und die allgemeinere Lehre, die über TypeScript hinausgeht: Ein Werkzeug, das nichts meldet, ist nicht dasselbe wie ein Werkzeug, das nichts findet. Dauerhaftes Grün ohne einen einzigen roten Lauf ist kein Beweis für sauberen Code — es kann auch heißen, dass niemand mehr hinschaut. Wer Prüfwerkzeuge einsetzt, sollte gelegentlich absichtlich einen Fehler einbauen und nachsehen, ob er auffällt.

Der Lernpfad mit ehrlichen Zeitangaben

Jetzt zum eigentlichen Thema. Die Zeitangaben unten sind Erfahrungswerte für konzentrierte Arbeitszeit — nicht Kalenderzeit, nicht „nebenbei mit Video im Hintergrund”. Wer täglich eine Stunde investiert, rechnet grob mit dem Doppelten an Kalendertagen.

Und die unbequeme Vorbemerkung: Es gibt keinen Zustand „TypeScript gelernt”. Es gibt „ich kann damit arbeiten”, und das kommt früher, als die meisten Kursanbieter suggerieren. Und es gibt „ich verstehe, was der Compiler mir sagt”, was deutlich später kommt, als dieselben Anbieter zugeben.

Stufe 1 — Einrichten und erster Fehler (1 bis 2 Stunden)

Ziel: Ein Projekt, in dem tsc läuft und Ihnen einen echten Fehler zeigt.

mkdir mein-ts-projekt && cd mein-ts-projekt
npm init -y
npm install --save-dev typescript
npx tsc --init

Der letzte Befehl legt eine tsconfig.json an. Was dort landet, hat sich geändert und ist für Anfänger wichtig genug, um es abzudrucken. Das sind die aktiven Einstellungen aus unserem Lauf mit 7.0.2:

{
  "compilerOptions": {
    "module": "nodenext",
    "target": "esnext",
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "exactOptionalPropertyTypes": true,
    "verbatimModuleSyntax": true,
    "isolatedModules": true,
    "noUncheckedSideEffectImports": true,
    "moduleDetection": "force",
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true,
    "jsx": "react-jsx",
    "skipLibCheck": true,
    "types": []
  }
}

Das ist deutlich strenger als die Voreinstellung früherer Jahre. Und jetzt kommt der Teil, der Anfänger regelmäßig zur Verzweiflung bringt — wir haben ihn nachgestellt. Völlig normaler, korrekter JavaScript-Code:

const namen = ["Ada", "Alan", "Grace"];
const erster = namen[0];
console.log(erster.toUpperCase());

In einem frisch per tsc --init erzeugten Projekt sagt der Compiler dazu:

src/index.ts(3,13): error TS18048: 'erster' is possibly 'undefined'.

Verständliche erste Reaktion: „Das ist doch offensichtlich ein String, das Array steht direkt darüber!” Der Compiler hat trotzdem recht, und zwar aus einem Grund, den man nur einmal begreifen muss: namen[0] ist keine Zusicherung. Bei einem leeren Array liefert dieser Ausdruck undefined, und JavaScript wirft dabei keinen Fehler — Sie bekommen einfach undefined und stürzen erst eine Zeile später ab. Das ist die Option noUncheckedIndexedAccess, und sie fängt eine der häufigsten Fehlerquellen überhaupt ab.

Die saubere Lösung ist eine Zeile:

const namen = ["Ada", "Alan", "Grace"];
const erster = namen[0];
if (erster !== undefined) {
  console.log(erster.toUpperCase());
}

// oder kompakter, mit Standardwert:
console.log((namen[0] ?? "unbekannt").toUpperCase());

Unser Rat für Stufe 1: Lassen Sie die strengen Voreinstellungen an. Es ist verlockend, noUncheckedIndexedAccess abzuschalten, wenn es einen anmeckert. Aber Sie lernen dann eine schwächere Sprache und müssen die Lektion später unter Zeitdruck nachholen. Der Schmerz ist am Anfang am billigsten.

Wer den Aufbau eines Projekts erst einmal umgehen und nur Syntax ausprobieren will: Der TypeScript Playground läuft im Browser, ohne Installation und ohne tsconfig.json. Für die ersten Experimente mit Typen ist das der schnellste Weg — Sie schreiben links, sehen rechts sofort das Ergebnis.

Stufe 2 — Die sechs Konzepte, die 90 % abdecken (4 bis 8 Stunden)

Hier liegt der eigentliche Hebel. TypeScript hat ein enormes Typsystem, aber im Alltag benutzt man immer dieselbe kleine Auswahl.

1. Primitive Annotationen. Das Fundament, in zwei Minuten gelernt:

let alter: number = 34;
let name: string = "Ada";
let aktiv: boolean = true;
let markierungen: string[] = ["neu", "wichtig"];
let irgendwas: unknown = holeDaten();

Wichtig: Sie müssen das meistens gar nicht hinschreiben. TypeScript leitet Typen selbst ab:

let alter = 34;        // ist automatisch number
const name = "Ada";    // ist automatisch der Literaltyp "Ada"

Ein häufiger Anfängerfehler ist, jede Variable zu annotieren. Das bläht den Code auf, ohne Sicherheit zu gewinnen. Annotieren Sie Funktionsgrenzen — Parameter und Rückgabewerte. Den Rest macht die Ableitung.

2. Interfaces und Type-Aliase — die Form Ihrer Daten.

interface Benutzer {
  id: number;
  name: string;
  email?: string;        // optional — kann fehlen
  readonly erstelltAm: Date;  // nach dem Anlegen nicht änderbar
}

function begruesse(b: Benutzer): string {
  return `Hallo, ${b.name}`;
}

type kann dasselbe und noch mehr:

type Benutzer = { id: number; name: string };
type Kennung = string | number;          // Union — das eine ODER das andere
type MitZeitstempel = Benutzer & { aktualisiertAm: Date };  // Schnittmenge

Wann was? Ehrliche Antwort: Es ist im Alltag fast egal. interface für Objektformen, die andere erweitern könnten; type für alles andere, besonders für Unions. Wenn Sie unsicher sind, nehmen Sie type — es kann alles, was interface kann, plus Unions.

3. Union-Typen und Narrowing — das Konzept mit dem größten Ertrag.

Ein Union-Typ sagt: „eins aus dieser Liste”. Narrowing ist das, was der Compiler tut, wenn Sie ihn davon überzeugen, welches es gerade ist:

function laenge(x: string | string[]): number {
  if (typeof x === "string") {
    return x.length;      // hier weiß der Compiler: string
  }
  return x.length;        // und hier: string[]
}

Sie schreiben eine gewöhnliche if-Abfrage, wie Sie es in JavaScript auch täten. Der Compiler liest mit. Das ist der Moment, in dem TypeScript für die meisten „klick” macht: Sie müssen dem Compiler nichts beweisen, Sie müssen nur normalen defensiven Code schreiben, und er versteht ihn.

Besonders nützlich sind Unions aus Zeichenketten-Literalen. Sie ersetzen enum vollständig, funktionieren mit node datei.ts, und die Fehlermeldung ist unschlagbar hilfreich:

type Status = "offen" | "erledigt";
const s: Status = "Offen";
error TS2820: Type '"Offen"' is not assignable to type 'Status'. Did you mean '"offen"'?

Der Compiler hat den Tippfehler erkannt und den richtigen Wert vorgeschlagen. Das ist wörtlich die Ausgabe aus unserem Test — keine Nacherzählung.

4. Funktionen richtig typisieren.

function addiere(a: number, b: number): number {
  return a + b;
}

const verdopple = (x: number): number => x * 2;

// Optionale Parameter und Standardwerte
function begruesse(name: string, gruss: string = "Hallo"): string {
  return `${gruss}, ${name}`;
}

// Funktion als Parameter
function verarbeite(werte: number[], transform: (n: number) => number): number[] {
  return werte.map(transform);
}

Rückgabetypen hinschreiben oder nicht? Der Compiler leitet sie ab, Sie müssen also nicht. Wir empfehlen es trotzdem für alles, was eine Datei verlässt — bei einer exportierten Funktion ist der Rückgabetyp ein Versprechen an alle Aufrufer. Ohne Annotation kann eine kleine Änderung im Rumpf still den Vertrag ändern, und der Fehler taucht dann irgendwo weit weg auf.

5. Generics — später, als Sie denken.

Generics sind Typen mit Platzhalter. Sie brauchen sie deutlich seltener als Tutorials suggerieren, aber wenn, dann sind sie unersetzlich:

function ersterEintrag<T>(arr: T[]): T | undefined {
  return arr[0];
}

const a = ersterEintrag([1, 2, 3]);        // number | undefined
const b = ersterEintrag(["x", "y"]);       // string | undefined

Das <T> heißt: „Ich weiß nicht, was drin ist, aber was rein geht, kommt raus.” Ohne Generics müssten Sie diese Funktion für jeden Typ neu schreiben oder any verwenden und alle Sicherheit aufgeben.

Unser Rat: Benutzen Sie Generics ab Tag eins, sie stecken in Array<T>, Promise<T>, Map<K, V>. Schreiben Sie eigene erst, wenn Sie dieselbe Funktion zum dritten Mal für einen anderen Typ kopiert haben. Vorher ist es fast immer verfrühte Abstraktion.

6. unknown statt any — die wichtigste Gewohnheit überhaupt.

any schaltet die Typprüfung ab. Es ist eine Notluke und wird als solche gebraucht — aber jedes any ist ein Loch im Netz.

const daten: unknown = JSON.parse('{"a":1}');
console.log(daten.a);
error TS18046: 'daten' is of type 'unknown'.

Der Compiler zwingt Sie, erst nachzusehen. Genau das ist der Sinn:

const daten: unknown = JSON.parse(rohText);

if (typeof daten === "object" && daten !== null && "a" in daten) {
  console.log(daten.a);   // jetzt erlaubt
}

Das ist mehr Schreibarbeit, und es ist an genau der Stelle richtig, an der Ihre Daten von außen kommen. JSON.parse liefert übrigens standardmäßig any — es ist eine der wenigen Stellen, an denen die Standardbibliothek Ihnen die Sicherheit stillschweigend wegnimmt. Wer unknown explizit hinschreibt, holt sie sich zurück.

Konsolen-Panel mit einer roten Wellenlinie unter einer Codezeile, die sich in ein grünes Häkchen verwandelt, daneben eine Lupe

Stufe 3 — Compiler-Fehler lesen lernen (2 bis 4 Stunden, verteilt)

Das ist die Fähigkeit, die den Unterschied macht, und sie steht in kaum einem Tutorial. Deshalb hier die Fehlermeldungen, die Sie in den ersten Wochen wirklich sehen — alle wörtlich aus unseren Testläufen mit TypeScript 7.0.2, nicht aus dem Gedächtnis:

CodeWortlautWas tatsächlich gemeint ist
TS2322Type 'string' is not assignable to type 'number'.Sie legen den falschen Datentyp in eine Variable. Der klassische Einstiegsfehler.
TS2345Argument of type 'string' is not assignable to parameter of type 'number'.Dasselbe, aber beim Funktionsaufruf. Prüfen Sie die Reihenfolge der Argumente.
TS2339Property 'email' does not exist on type '{ name: string; }'.Sie greifen auf ein Feld zu, das im Typ nicht vorkommt. Meist ein Tippfehler oder ein zu enger Typ.
TS18048'n' is possibly 'undefined'.Der Wert könnte fehlen. Vorher prüfen oder ?? nutzen.
TS18047'el' is possibly 'null'.Fast immer document.getElementById — das liefert null, wenn nichts gefunden wird.
TS2820Type '"Offen"' is not assignable to type 'Status'. Did you mean '"offen"'?Tippfehler in einem Literal-Union. Der Compiler nennt die Lösung mit.
TS18046'daten' is of type 'unknown'.Sie müssen den Typ erst eingrenzen, bevor Sie zugreifen.
TS2741Property 'y' is missing in type '{ x: number; }' but required in type 'Punkt'.Ein Pflichtfeld fehlt im Objekt.
TS7006Parameter 'a' implicitly has an 'any' type.Unter strict müssen Funktionsparameter einen Typ haben. Typischer erster Fehler beim Umbenennen von .js zu .ts.

Zwei Lesetechniken, die viel Zeit sparen:

Erstens: Lesen Sie von hinten nach vorn. Bei geschachtelten Meldungen steht die eigentliche Ursache ganz unten in der am weitesten eingerückten Zeile. Beispiel aus unserem Test:

error TS2375: Type '{ host: string; port: undefined; }' is not assignable to type 'Config'
  with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of
  the target's properties.
    Types of property 'port' are incompatible.
      Type 'undefined' is not assignable to type 'number'.

Die erste Zeile ist Kontext. Die letzte ist die Diagnose: port ist undefined, soll aber number sein.

Zweitens: Die Fehlernummer ist ein besserer Suchbegriff als der Text. TS2345 findet gezielte Erklärungen; die Textmeldung enthält Ihre eigenen Typnamen und liefert deshalb keine brauchbaren Treffer.

Stufe 4 — Ein echtes Projekt schreiben (10 bis 40 Stunden)

Ab hier hilft kein Tutorial mehr, nur noch Arbeit an etwas, das Sie interessiert. Bauen Sie etwas mit einer API-Anbindung — da lernen Sie den wichtigsten Teil: die Grenze zwischen typisierter und untypisierter Welt.

interface WetterAntwort {
  temperatur: number;
  ort: string;
}

// Naiv — und still gefährlich:
async function holeWetterNaiv(ort: string): Promise<WetterAntwort> {
  const res = await fetch(`https://api.example.com/wetter?ort=${ort}`);
  return res.json() as WetterAntwort;   // eine BEHAUPTUNG, keine Prüfung
}

Das as ist eine Zusicherung an den Compiler, keine Kontrolle. Ändert die API ihr Format, kompiliert Ihr Code weiterhin fehlerfrei und stürzt zur Laufzeit ab. Der ehrliche Weg prüft:

function istWetterAntwort(x: unknown): x is WetterAntwort {
  return (
    typeof x === "object" && x !== null &&
    "temperatur" in x && typeof (x as Record<string, unknown>).temperatur === "number" &&
    "ort" in x && typeof (x as Record<string, unknown>).ort === "string"
  );
}

async function holeWetter(ort: string): Promise<WetterAntwort> {
  const res = await fetch(`https://api.example.com/wetter?ort=${ort}`);
  const roh: unknown = await res.json();
  if (!istWetterAntwort(roh)) {
    throw new Error("Unerwartetes Antwortformat der Wetter-API");
  }
  return roh;   // ab hier garantiert richtig geformt
}

Das x is WetterAntwort heißt Type Guard: eine Funktion, deren Rückgabe dem Compiler etwas über den Typ verrät. Ab dem if weiß er Bescheid. In größeren Projekten übernehmen Bibliotheken wie Zod oder Valibot diese Arbeit — aber schreiben Sie es einmal von Hand, sonst bleibt das Prinzip abstrakt.

Zeitangabe ehrlich: Ein kleines, echtes Projekt kostet 10 bis 40 Stunden, je nach Umfang. Danach sind Sie produktiv. Sie werden weiter nachschlagen — das hören wir auch nach Jahren nicht auf.

Stufe 5 — Souveränität (3 bis 6 Monate nebenbei)

Utility Types (Partial, Pick, Omit, Record, ReturnType), Conditional Types, Template Literal Types, infer, Deklarationsdateien für untypisierte Bibliotheken. Das kommt beim Arbeiten, nicht beim Lernen.

Ein Konzept aus dieser Stufe ist die Ausnahme, weil es früh nützlich ist — satisfies:

const routen = {
  home: "/",
  blog: "/blog",
} satisfies Record<string, `/${string}`>;

const h: string = routen.home;    // bleibt der genaue Literaltyp "/"

satisfies prüft, ob Ihr Objekt zu einem Typ passt, ohne den abgeleiteten Typ zu verbreitern. Mit const routen: Record<string, string> verlören Sie die Information, welche Schlüssel es gibt. Mit satisfies behalten Sie sie und bekommen trotzdem die Prüfung. Für Konfigurationsobjekte ist das der richtige Griff.

Was Sie hier NICHT tun sollten: Typ-Akrobatik um ihrer selbst willen. Es gibt beeindruckende Typen, die im Netz herumgereicht werden — mehrstufige Conditional Types mit rekursivem infer. Faustregel: Wenn Ihr Typ schwerer zu lesen ist als der Code, den er absichert, hat er sein Ziel verfehlt. Typen sind Dokumentation, die geprüft wird. Unlesbare Dokumentation ist keine.

Ein bestehendes JavaScript-Projekt migrieren

Der häufigste reale Fall: Es gibt schon Code, und er soll nicht stillstehen. Der Fehler, den fast alle machen, ist die große Umstellung an einem Wochenende. Das endet in hunderten Fehlern gleichzeitig, und niemand weiß mehr, welcher davon echt ist.

Brücke aus leuchtenden Blöcken zwischen einer gelben und einer blauen Insel, über die Dateien einzeln mit Häkchen hinüberwandern

Der Weg, der funktioniert, ist schrittweise.

Schritt 1: TypeScript hinzufügen, ohne etwas umzubenennen.

npm install --save-dev typescript
npx tsc --init

Dann in der tsconfig.json allowJs einschalten und strict zunächst aus. Sie kompilieren jetzt Ihr JavaScript mit dem TypeScript-Compiler. Noch prüft er kaum etwas — das ist der Punkt. Sie stellen sicher, dass die Werkzeugkette läuft, bevor Sie Regeln verschärfen.

Schritt 2: checkJs einschalten und erschrecken.

Damit prüft der Compiler auch .js-Dateien. Wir haben es an typischem Altcode ausprobiert:

function summe(a, b) { return a + b; }
const total = summe(1, "2");
migr/legacy.js(1,16): error TS7006: Parameter 'a' implicitly has an 'any' type.
migr/legacy.js(1,19): error TS7006: Parameter 'b' implicitly has an 'any' type.

Bemerkenswert ist, was der Compiler nicht meldet: summe(1, "2") — der eigentliche Fehler, eine Zahl plus eine Zeichenkette. Er kann ihn nicht sehen, weil die Parameter typlos sind und damit alles erlauben. Ohne Typen keine Prüfung, und die fehlende Prüfung sieht genauso aus wie eine bestandene. Das ist das ganze Argument für TypeScript in zwei Zeilen Code.

Schritt 3: JSDoc — Typen ohne Dateiumbenennung.

Wenig bekannt und für Migrationen sehr nützlich: Sie können in reinen .js-Dateien typisieren, per Kommentar.

/**
 * @param {number} a
 * @param {number} b
 * @returns {number}
 */
function summe(a, b) { return a + b; }
summe(1, "2");
migr/jsdoc.js(7,10): error TS2345: Argument of type 'string' is not assignable
to parameter of type 'number'.

Jetzt findet er den echten Fehler — in einer .js-Datei, ohne Build-Schritt, ohne Umbenennung. Für Projekte, bei denen eine Umstellung politisch oder technisch schwierig ist, ist das der Fuß in der Tür. Bibliotheken wie Svelte haben aus genau diesem Grund eine Weile auf JSDoc statt .ts gesetzt.

Schritt 4: Datei für Datei umbenennen. Fangen Sie bei den Blättern des Abhängigkeitsbaums an — Hilfsfunktionen, Konstanten, reine Datenmodelle. Diese Dateien importieren wenig und werden von vielen benutzt, also strahlt jeder gewonnene Typ nach oben aus. Zentrale Dateien mit vielen Abhängigkeiten kommen zuletzt.

Schritt 5: strict einschalten, wenn genug umgestellt ist. Nicht am Anfang, sonst ertrinken Sie in TS7006. Wenn Sie es aktivieren, tun Sie es zuerst einzeln (noImplicitAny, dann strictNullChecks), nicht alles gleichzeitig.

Realistische Zeitangabe: Für ein mittleres Projekt mit 20.000 bis 50.000 Zeilen sind mehrere Wochen nebenher realistisch — nicht Vollzeit, aber verteilt. Wer Ihnen „ein Nachmittag” verspricht, hat entweder ein sehr kleines Projekt oder any großzügig eingesetzt.

Die strengen Optionen — was sie kosten und was sie bringen

Da tsc --init heute mehrere strenge Schalter vorgibt, hier die drei, über die Sie stolpern werden, jeweils mit dem echten Fehlertext.

Kontrollpanel mit einer Reihe von Kippschaltern, teils leuchtend eingeschaltet, verbunden mit einem zentralen Schildsymbol

noUncheckedIndexedAccess

Jeder Zugriff per Index liefert zusätzlich undefined.

const namen: string[] = ["Ada", "Alan"];
const erster: string = namen[0];
error TS2322: Type 'string | undefined' is not assignable to type 'string'.
  Type 'undefined' is not assignable to type 'string'.

Kosten: Sie schreiben mehr Prüfungen. Nutzen: Sie fangen die Klasse von Fehlern ab, die in der Produktion als „Cannot read properties of undefined” erscheint. Unsere Empfehlung: anlassen.

exactOptionalPropertyTypes

Unterscheidet „Feld fehlt” von „Feld ist ausdrücklich undefined”.

interface Config { host: string; port?: number }
const c: Config = { host: "localhost", port: undefined };
error TS2375: Type '{ host: string; port: undefined; }' is not assignable to type
'Config' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to
the types of the target's properties.

Der Unterschied ist subtil, aber real: { host: "x" } und { host: "x", port: undefined } verhalten sich bei Object.keys, in und beim Serialisieren nach JSON unterschiedlich. Kosten: gelegentliche Verwirrung. Nutzen: kein Rätselraten über Konfigurationsobjekte. Für Einsteiger vertretbar zum Abschalten, wenn es zu viel wird — aber wissen, was man abschaltet.

verbatimModuleSyntax

Der Schalter mit dem größten Überraschungspotenzial. Wir haben ihn absichtlich falsch benutzt, um zu zeigen, was passiert:

import { User } from "./vms1.js";
export const u: User = { id: 1 };
error TS1295: ECMAScript imports and exports cannot be written in a CommonJS file
under 'verbatimModuleSyntax'. ...
error TS1484: 'User' is a type and must be imported using a type-only import when
'verbatimModuleSyntax' is enabled.

Drei Fehler für zwei harmlos aussehende Zeilen. Die Lösung für den zweiten ist ein Wort:

import type { User } from "./vms1.js";

import type sagt: „Das ist nur ein Typ, wirf den Import beim Übersetzen weg.” Ohne diese Angabe müsste das Werkzeug raten, ob der Import zur Laufzeit gebraucht wird — und genau das Raten schaltet verbatimModuleSyntax ab. Es ist deshalb Voraussetzung für schnelle Übersetzer wie esbuild und für node datei.ts.

Der erste Fehler (TS1295) hat übrigens gar nichts mit Typen zu tun: Unsere Testdatei lag in einem Ordner ohne "type": "module" in der package.json, galt damit als CommonJS und durfte kein import benutzen. Gewöhnen Sie sich an, "type": "module" in neue Projekte zu schreiben — ein großer Teil der rätselhaften Modulfehler löst sich damit auf.

Der ehrliche Teil: Wann TypeScript sich NICHT lohnt

Wir haben viel Gutes über TypeScript geschrieben, weil viel Gutes stimmt. Aber es gibt Fälle, in denen die Kosten den Nutzen übersteigen. Wer das verschweigt, verkauft statt zu beraten.

Eine Waage, die einen schweren Werkzeugkasten gegen eine leichte Feder abwägt, daneben ein Stoppschild und ein Fragezeichen

Ein Skript unter 200 Zeilen, das Sie einmal ausführen. Ein Wartungsskript, eine einmalige Datenmigration, ein Cronjob mit dreißig Zeilen. Der Aufwand für Konfiguration und Build steht in keinem Verhältnis. Schreiben Sie es in JavaScript oder Python und lassen Sie es laufen. Typen amortisieren sich über Wartung — ohne Wartung keine Amortisation.

Prototypen, die wirklich weggeworfen werden. Wenn Sie erkunden, ob eine Idee überhaupt trägt, ist die Datenform noch täglich im Fluss. Typen zu pflegen, die sich stündlich ändern, ist Ballast. Der Haken: „Wir schreiben das später neu” ist eine der häufigsten Selbsttäuschungen unserer Branche. Wenn der Prototyp eine echte Chance hat, in Produktion zu landen, gilt der Absatz nicht mehr.

Ein Team, das es nicht will. Das ist ein sozialer, kein technischer Grund, und trotzdem der entscheidende. TypeScript gegen den Widerstand eines Teams durchzusetzen, erzeugt vorhersehbar any an jeder unbequemen Stelle, @ts-ignore über jedem Fehler und ein Typsystem, das behauptet, den Code abzusichern, während es das nicht tut. Das ist schlechter als gar kein TypeScript — weil es Sicherheit vortäuscht, die niemand mehr prüft. Überzeugen Sie zuerst, migrieren Sie danach.

Sehr dynamischer Code. Manche Aufgaben — Plugin-Systeme, die zur Laufzeit Objekte zusammensetzen, generische Datenverarbeitung mit unbekannter Struktur, stark metaprogrammierte Bibliotheken — lassen sich nur mit erheblichem Typ-Akrobatik-Aufwand beschreiben. Wenn Sie merken, dass Sie mehr Zeit mit dem Typsystem als mit dem Problem verbringen, ist das ein Signal. unknown an der Grenze und eine ehrliche Laufzeitprüfung sind dann oft die bessere Antwort als ein virtuoser Typ.

Sie lernen gerade programmieren. Steht oben schon, gehört aber hierher: Zwei neue Systeme gleichzeitig zu lernen — Programmierlogik und Typsystem — verdoppelt nicht die Schwierigkeit, es multipliziert sie. Weil Sie bei jedem Fehler nicht wissen, aus welcher der beiden Welten er stammt.

Und wo TypeScript überschätzt wird: Es findet Typfehler. Es findet keine Denkfehler. Ein Programm, das den Mehrwertsteuersatz falsch berechnet, kompiliert makellos. Ein sort, das aufsteigend statt absteigend sortiert, ebenso. TypeScript ersetzt keine Tests, es ergänzt sie. Wir haben Teams gesehen, die nach der Umstellung ihre Testabdeckung senkten — mit vorhersehbarem Ergebnis.

Werkzeuge, die den Einstieg leichter machen

Ihr Editor ist das wichtigste Werkzeug. Der Sprachserver zeigt Fehler beim Tippen, lange bevor Sie tsc aufrufen. Und dieser Weg lief bei uns auch dann, als der Watch-Modus streikte — ein Grund mehr, sich auf die Editor-Anzeige zu verlassen und den Compiler zusätzlich vor jedem Commit laufen zu lassen.

Der Playground zum Ausprobieren. Wenn Sie eine Frage vom Typ „Was passiert, wenn ich…” haben, ist ein Projekt aufzusetzen zu langsam. Unser TypeScript Playground läuft direkt im Browser: Code links, Ergebnis rechts, keine Installation. Für das Durcharbeiten der Beispiele aus diesem Artikel ist das der schnellste Weg.

KI-Assistenten sind bei TypeScript ungewöhnlich hilfreich — gerade beim Lernen, weil Fehlermeldungen ein Format haben, das Modelle gut auflösen. Statt eine Fehlernummer zu suchen, fügen Sie die Meldung samt Codezeile ein und fragen nach der Ursache. Welche Werkzeuge dafür heute taugen, haben wir in unserem Vergleich der besten KI-Coding-Tools durchgetestet.

Eine Warnung dazu, die wir für wichtig halten: Sprachmodelle sind auf Code aus der Vergangenheit trainiert. Bei einem Umbruch wie TypeScript 7 heißt das, dass Sie mit einiger Sicherheit Antworten bekommen, die den Stand von Version 5 beschreiben — inklusive Empfehlungen zu require('typescript'), das, wie oben gemessen, nicht mehr funktioniert. Prüfen Sie Versionsaussagen immer selbst nach. Ein npm view typescript version dauert zwei Sekunden und ist die einzige Quelle, die nicht altert.

Für Framework-Arbeit: Wenn Sie TypeScript im Zusammenhang mit Next.js lernen, ist der Bereich mit den meisten Typfragen erfahrungsgemäß das Routing — insbesondere seit Route-Parameter asynchron sind. Wir haben das ausführlich in unserem Leitfaden zu Next.js Dynamic Routes behandelt; die dortigen Beispiele sind ein guter Praxistest für alles, was Sie hier über Promise<T> und Narrowing gelernt haben.

Für die Dokumentation Ihres Projekts: Sauber getippter Code verdient eine lesbare README. Unser Markdown-Generator nimmt Ihnen das Formatieren ab, wenn Sie Ihr erstes TypeScript-Projekt veröffentlichen.

Häufige Fragen

Muss ich JavaScript können, bevor ich TypeScript lerne? Für Gruppe B (echte Einsteiger): ja, mindestens die Grundlagen. Nicht wegen der Syntax, sondern wegen der Fehlerdiagnose — Sie müssen einen Denkfehler von einer Typverletzung unterscheiden können. Rechnen Sie mit 40 bis 80 Stunden JavaScript vorweg.

Wie lange dauert TypeScript lernen wirklich? Für JS-Entwickler: 8 bis 15 Stunden konzentrierte Arbeit bis zum produktiven Einsatz, 3 bis 6 Monate nebenbei bis zur Souveränität. Für Einsteiger: die JavaScript-Zeit obendrauf. Alles unter „ein Wochenende” bezieht sich auf Syntaxkenntnis, nicht auf Können.

Sollte ich mit TypeScript 6 oder 7 anfangen? Für ein neues Lernprojekt: Version 7 (aktuell 7.0.2, Stand 4. August 2026). Sie ist schneller und die Sprache ist dieselbe. Bei einem bestehenden Projekt mit gewachsener Werkzeugkette lohnt sich Vorsicht — prüfen Sie, ob Ihre Werkzeuge die Compiler-API benutzen. Und behalten Sie den Watch-Modus im Auge, siehe oben.

Was ist der Unterschied zwischen interface und type? Im Alltag fast keiner. interface lässt sich durch mehrfache Deklaration erweitern (nützlich für Bibliotheks-Typen), type kann zusätzlich Unions, Schnittmengen und Conditional Types. Im Zweifel type.

Warum meckert TypeScript bei array[0]? Das ist noUncheckedIndexedAccess, eine Voreinstellung von tsc --init. Der Zugriff kann undefined liefern, wenn das Array leer ist. Prüfen Sie mit if oder nutzen Sie ?? standardwert. Lassen Sie die Option an — sie fängt echte Produktionsfehler ab.

Kann ich TypeScript ohne Build-Schritt benutzen? Teilweise. Node führt .ts-Dateien direkt aus, entfernt dabei aber nur die Typen und prüft nichts. Für die Prüfung brauchen Sie weiterhin tsc --noEmit. Zusätzlich sind Konstrukte wie enum im Strip-Modus verboten — mit erasableSyntaxOnly weist der Compiler Sie vorab darauf hin.

Ist any immer schlecht? Nein, aber es ist immer eine Ausnahme. Als Übergang bei einer Migration ist es legitim. Als Dauerlösung höhlt es das Typsystem aus. Wenn Sie einen Fluchtweg brauchen, nehmen Sie unknown — es zwingt Sie an der Verwendungsstelle zur Prüfung, statt sie stillschweigend zu überspringen.

Verlangsamt TypeScript meine Anwendung? Nein, zur Laufzeit existiert kein einziges Typ-Artefakt. Was Zeit kostet, ist die Übersetzung während der Entwicklung — und genau die ist mit Version 7 in unserer Messung um den Faktor 3,8 kürzer geworden.

Fazit

TypeScript lernen ist weniger Aufwand, als der Ruf der Sprache vermuten lässt, und mehr Aufwand, als Kursanbieter versprechen. Für JavaScript-Entwickler ist der produktive Einstieg eine Sache von 8 bis 15 Stunden; die Souveränität kommt über Monate der Anwendung und lässt sich nicht abkürzen.

Die drei Dinge, die wir Ihnen mitgeben würden:

Erstens: Lernen Sie Fehlermeldungen zu lesen, nicht Features auswendig. Die Konzepte aus Stufe 2 decken den Alltag ab. Was Sie tatsächlich von Anfängern unterscheidet, ist die Fähigkeit, bei TS2345 sofort zu wissen, wo Sie nachsehen müssen.

Zweitens: Lassen Sie die strengen Voreinstellungen an. Sie sind am Anfang lästig und genau dann am billigsten. noUncheckedIndexedAccess fängt einen Fehler ab, der Sie sonst irgendwann um drei Uhr nachts in der Produktion besucht.

Drittens: Vertrauen Sie keinem Werkzeug, das nur schweigt. Unser Watch-Modus meldete stundenlang „0 errors” — und schaute dabei nie in unser Quellverzeichnis. Ein grüner Lauf beweist erst dann etwas, wenn Sie einmal gesehen haben, dass derselbe Aufbau auch rot werden kann. Bauen Sie gelegentlich absichtlich einen Fehler ein. Das ist der billigste Test, den es gibt, und der einzige, der Ihre Prüfwerkzeuge selbst prüft.

Alle Versions- und Zeitangaben in diesem Artikel wurden am 4. August 2026 gemessen. Prüfen Sie den aktuellen Stand mit npm view typescript version — und wenn dort etwas anderes steht, glauben Sie der Kommandozeile, nicht diesem Artikel.