Schreibgeschützte Arrays
Eine Funktion bekommt keine eigene Kopie eines Arrays, sondern dasselbe Array, das der Aufrufer hat. Sie kann also ein Array ändern, das ihr gar nicht gehört. Diese Funktion soll die Tränke in einem Beutel zählen, und das tut sie auch, aber sieh dir den Beutel danach an:
const beutel = ["Trank", "Seil", "Trank"];
function zaehleTraenke(gegenstaende: string[]): number {
let anzahl = 0;
while (gegenstaende.length > 0) {
if (gegenstaende.pop() === "Trank") {
anzahl++;
}
}
return anzahl;
}
console.log(zaehleTraenke(beutel));
console.log(beutel);Das gibt aus:
2
[]pop() nimmt das letzte Element aus dem Array, nach dem Zählen ist der Beutel also leer. In einem großen Programm ist so ein Fehler schwer zu finden: Der Beutel leert sich in einer Funktion, die scheinbar nur gezählt hat. TypeScript kann das verhindern. Schreibe readonly vor den Array-Typ:
function zaehleTraenke(gegenstaende: readonly string[]): number {main.ts(6,26): error TS2339: Property 'pop' does not exist on type 'readonly string[]'.Ein readonly string[] ist ein Array, das du lesen, aber nicht ändern kannst. Ein Element lesen, length, for...of, includes, find, map und filter funktionieren alle (map und filter erzeugen ein neues Array). Aber es gibt kein push, kein pop und keine Zuweisung an ein Element: gegenstaende[0] = "Schwert" ergibt Index signature in type 'readonly string[]' only permits reading. Bei einem Parameter ist readonly ein Versprechen, das der Aufrufer schon in der ersten Zeile der Funktion sieht: Diese Funktion liest das Array nur.
Du kannst denselben Typ auch als ReadonlyArray<string> schreiben, so wie sich string[] als Array<string> schreiben lässt. In Fehlermeldungen schreibt TypeScript readonly string[].
Ein normales Array darf an einen readonly-Parameter übergeben werden: Die Funktion liest es nur. Andersherum geht es nicht. Ein schreibgeschütztes Array, etwa eine Liste mit as const aus der Lektion „Daten modellieren“, darf nicht an einen string[]-Parameter übergeben werden, weil diese Funktion es ändern könnte:
const klassen = ["Krieger", "Magier", "Waldläufer"] as const;
function gibAlleAus(namen: string[]): void {
for (const name of namen) {
console.log(name);
}
}
gibAlleAus(klassen);main.ts(9,12): error TS4104: The type 'readonly ["Krieger", "Magier", "Waldläufer"]' is 'readonly' and cannot be assigned to the mutable type 'string[]'.Eine Funktion, die ein Array nur liest, sollte also ein readonly-Array annehmen: Dann akzeptiert sie beide. Und wenn sie ein Array mit etwas mehr zurückgeben soll, erzeugt sie mit Spread ein neues: [...gegenstaende, "Alte Karte"].
Für Objekte gibt es einen Utility-Typ: Readonly<Held> ist Held, bei dem jede Eigenschaft readonly ist. Es ist, als hättest du vor jede Eigenschaft readonly geschrieben wie in der Lektion „Objekttypen“, aber nur dort, wo du es verwendest: held: Readonly<Held> bei einem Parameter bedeutet, dass die Funktion den Helden nicht ändert, und held.leben = 0 darin ergibt Cannot assign to 'leben' because it is a read-only property. Wie jeder Typ wird auch readonly nur von TypeScript geprüft. Das JavaScript, das läuft, weiß nichts davon.
Typische Fehler:
readonlysteht nur vor Typen mit[].readonly Array<string>ergibt'readonly' type modifier is only permitted on array and tuple literal types.Schreibereadonly string[]oderReadonlyArray<string>.- Eine Funktion, die
string[]zurückgeben soll, gibt den Parameter selbst zurück:The type 'readonly string[]' is 'readonly' and cannot be assigned to the mutable type 'string[]'.Gib ein neues Array zurück.
So schreibst du es:
Anweisungen
- 1
Die Funktion
mitGegenstandsoll eine neue Liste zurückgeben, ändert aber die, die sie bekommt. Ändere den Typ ihres Parametersgegenstaendezureadonly string[]und führe das Programm aus: TypeScript meldet die Zeile mitpush. Ersetze den Rumpf der Funktion durchreturn [...gegenstaende, gegenstand];. - 2
Gib unter den Funktionen
mitGegenstand(inventar, "Alte Karte")aus und danachinventar. Das Inventar hat sich nicht verändert:["Heiltrank", "Seil", "Fackel", "Alte Karte"] ["Heiltrank", "Seil", "Fackel"] - 3
Die Funktion
lebenTextdarf den Helden auch nicht ändern. Ändere den Typ ihres Parameters zuReadonly<Held>und führe das Programm aus. TypeScript findet in der Funktion eine Zeile, die den Helden ändert. Behebe den Fehler: Ein einzelnes=weist einen Wert zu, du willst aber vergleichen. - 4
Gib unter den anderen Zeilen
lebenText(kira)aus:Kira: 34/50