TypeScript-Fehler: Index aus Union-Typ – Lösung für Anfänger

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Einleitung: Warum meckert TypeScript Ihren Code an?

\n\n

Haben Sie schon einmal TypeScript-Code geschrieben, der völlig logisch erscheint, der Compiler aber plötzlich einen erschreckenden Fehler ausgibt? Wenn Sie auf die Meldung «An index signature parameter type cannot be a union type. Consider using a mapped object type instead» gestoßen sind – Sie sind nicht allein. Dieser Fehler ist eine der häufigsten Fragen auf Stack Overflow (tausende Aufrufe!) und bringt selbst erfahrene Entwickler oft ins Grübeln.

\n\n

In diesem Artikel zeigen wir nicht nur, wie man den Fehler behebt. Wir analysieren, warum TypeScript so streng ist, und wie Sie mapped object types verwenden, um Ihren Code nicht nur funktionsfähig, sondern auch sicherer zu machen. Los geht's!

\n\n

Was ist ein index signature und wozu braucht man ihn?

\n\n

Stellen Sie sich vor, Sie erstellen ein Objekt, dessen Schlüssel Strings und dessen Werte Zahlen sind. Zum Beispiel ein Wörterbuch mit Produktpreisen:

\n\n
// Normales Objekt\nconst prices = {\n  apple: 100,\n  banana: 50,\n  cherry: 200\n};
\n\n

Was aber, wenn Sie TypeScript sagen wollen: «Hör zu, dieses Objekt kann beliebige String-Schlüssel haben, und alle Werte sind Zahlen»? Dafür braucht man den index signature – eine spezielle Syntax, die ein Muster für alle Eigenschaften eines Objekts beschreibt:

\n\n
// Index signature: [key: string]: number\ninterface PriceMap {\n  [key: string]: number;\n}\n\nconst prices: PriceMap = {\n  apple: 100,\n  banana: 50\n};
\n\n

Hier ist [key: string]: number der index signature. Er besagt: «Schlüssel sind Strings, Werte sind Zahlen». Ganz einfach, oder?

\n\n

Und wo liegt das Problem mit Union-Typen?

\n\n

Stellen Sie sich nun vor, Sie möchten die möglichen Schlüssel auf nur zwei Optionen beschränken: 'name' oder 'age'. Es scheint logisch, das so zu schreiben:

\n\n
// ❌ FEHLER! So geht das nicht\ninterface Person {\n  [key: 'name' | 'age']: string | number;\n}
\n\n

Und dann gibt TypeScript genau diesen Fehler aus: «An index signature parameter type cannot be a union type. Consider using a mapped object type instead».

\n\n

Warum? Weil der index signature dazu gedacht ist, eine unbegrenzte Menge von Schlüsseln zu beschreiben. Wenn Sie eine konkrete Liste von Schlüsseln angeben möchten, ist das kein Muster mehr, sondern eine genaue Beschreibung der Struktur. TypeScript erlaubt es nicht, diese Konzepte zu vermischen.

\n\n

Wie behebt man den Fehler? Verwenden Sie Mapped Object Type

\n\n

Die Lösung, die der Compiler selbst vorschlägt, ist die Verwendung eines mapped object type (zugeordneter Objekttyp). Das klingt kompliziert, ist aber in der Praxis nur eine Möglichkeit, alle Schlüssel aus einem Union-Typ zu «durchlaufen» und für jeden eine eigene Eigenschaft zu erstellen.

\n\n

So sieht das aus:

\n\n
// ✅ RICHTIG: mapped type verwenden\ntype Person = {\n  [K in 'name' | 'age']: K extends 'name' ? string : number;\n};\n\n// Oder eine einfachere Variante, wenn die Werttypen gleich sind:\ntype PersonSimple = {\n  [K in 'name' | 'age']: string | number;\n};
\n\n

Analysieren wir die Syntax [K in 'name' | 'age']:

\n
    \n
  • K – eine Variable, die nacheinander jeden Wert aus dem Union-Typ annimmt ('name', dann 'age').
  • \n
  • in – ein Schlüsselwort, das eine «Schleife» über die Typen startet.
  • \n
  • 'name' | 'age' – unsere Menge von Schlüsseln.
  • \n
\n\n

Als Ergebnis erstellt TypeScript ein Objekt mit zwei konkreten Eigenschaften: name und age. Der Fehler ist verschwunden!

\n\n

Beispiel mit unterschiedlichen Werttypen

\n\n

Oft kommt es vor, dass verschiedene Schlüssel unterschiedliche Werttypen haben sollen. Mit bedingten Typen (conditional types) lässt sich das elegant lösen:

\n\n
type Config = {\n  [K in 'host' | 'port' | 'debug']: \n    K extends 'host' ? string :\n    K extends 'port' ? number :\n    boolean;\n};\n\n// Jetzt:                

Blogs

Buchempfehlungen