Einleitung: Warum ein einzelner Typ langweilig ist
\n\nStellen Sie sich vor: Sie programmieren in TypeScript und stoßen plötzlich auf eine Situation, in der ein Array Daten verschiedener Typen speichern muss. Zum Beispiel eine Liste, in der jedes Element entweder ein string oder ein number ist. Oder ein Tupel aus einem Namen (Zeichenkette) und einem Alter (Zahl).
Viele Anfänger (und nicht nur sie) fragen sich: „Wie deklariere ich ein Array mit mehreren Typen in TypeScript?“ Diese Frage hat auf Stack Overflow tausende Aufrufe – und das aus gutem Grund. TypeScript ist streng bei Typen, bietet aber dennoch flexible Werkzeuge für solche Fälle.
\n\nIn diesem Artikel werden wir alle Methoden zur Arbeit mit Arrays gemischter Typen durchgehen: von einfachen Union-Typen über Tupel bis hin zu Generics. Sie erfahren, wann Sie welchen Ansatz verwenden und wie Sie der any-Falle entgehen.
1. Union Types: Der einfachste Weg
\n\nDie naheliegendste Variante ist die Verwendung eines Union Types (Typenvereinigung). Damit sagen Sie: „Das Array kann Elemente vom Typ string ODER number enthalten“.
// Array, das Strings oder Zahlen enthalten kann\nconst mixedArray: (string | number)[] = ['hallo', 42, 'welt', 100];\n\n// Alternative Schreibweise (äquivalent)\nconst mixedArray2: Array<string | number> = ['hallo', 42, 'welt', 100];\n\nHier bedeutet (string | number)[]: „ein Array, dessen jedes Element ein String oder eine Zahl ist“. TypeScript wird überprüfen, dass Sie nicht versuchen, etwa einen Boolean oder ein Objekt hinzuzufügen.
Wann ist das praktisch?
\n- \n
- Wenn die Reihenfolge der Elemente unwichtig ist, sondern nur die Menge der zulässigen Typen zählt. \n
- Wenn Sie mit einer API arbeiten, die ein Array heterogener Daten zurückgibt. \n
- Wenn Sie eine Liste von IDs (Zahlen) und Namen (Strings) in einem Array speichern. \n
Stolperfalle
\nBei der Verwendung von Union-Typen können Sie nicht garantieren, dass an erster Position ein String und an zweiter eine Zahl steht. Die Typisierung sagt nur: „Im Array gibt es Strings und Zahlen, aber in welcher Reihenfolge – unbekannt“.
\n\nconst arr: (string | number)[] = [1, 'hallo'];\n// TypeScript weiß nicht: arr[0] – ist es number oder string?\nconst first = arr[0]; // Typ: string | number\n// Um es als Zahl zu verwenden, muss der Typ eingeengt werden:\nif (typeof first === 'number') {\n console.log(first.toFixed(2));\n}\n\n2. Tupel (Tuples): Wenn die Reihenfolge wichtig ist
\n\nWenn Sie benötigen, dass das Array eine feste Struktur hat – z. B. zuerst ein String, dann eine Zahl, dann ein Boolean – verwenden Sie Tupel (Tuple Types).
\n\n// Tupel: [String, Zahl, Boolean]\nconst person: [string, number, boolean] = ['Alice', 30, true];\n\n// Tupel mit Labels (lesbarer)\nconst product: [name: string, price: number, inStock: boolean] = ['Laptop', 1200, true];\n\nTupel legen Anzahl der Elemente und Typ an jeder Position streng fest. Wenn Sie versuchen, einen Wert falschen Typs zuzuweisen oder ein zusätzliches Element hinzuzufügen, gibt TypeScript einen Fehler aus.
\n\nRest-Elemente in Tupeln
\nSeit TypeScript 4.0 ist es möglich, Rest-Elemente in Tupeln anzugeben. Das ist praktisch, wenn ein Teil der Struktur festgelegt ist und der Rest variabel:
\n\n// Erstes Element – String, restliche – Zahlen\nconst data: [string, ...number[]] = ['ergebnisse', 95, 87, 92];\n\n// Kombinierbar\nconst logEntry: [timestamp: Date, ...messages: string[]] = [new Date(), 'info', 'benutzer angemeldet'];\n\n3. Type Alias für komplexe Arrays
\n\nWenn die Struktur eines Arrays komplex wird, ist es praktisch, den Typ in einen separaten Alias (Pseudonym) auszulagern. Das verbessert die Lesbarkeit des Codes und ermöglicht die Wiederverwendung des Typs.
\n\ntype UserEntry = [id: number, name: string, email: string, isActive: boolean];\n\nconst users: UserE