Aufwärmen · Aufgabe 1 von 7
Zum Aufwärmen aus JavaScript: name hat einen Default-Wert. Was gibt das aus?
function greet(name = "guest") {
return "Hello, " + name;
}
console.log(greet(), greet(undefined), greet(null));// B4.2 · ca. 30 Min. · Einstieg
Nach dieser Lektion schreiben Sie Funktionen mit optionalen, Default- und beliebig vielen Argumenten, spreaden Arrays in Aufrufe und destrukturieren einen typisierten Parameter.
Danach können Sie
Aufwärmen · Aufgabe 1 von 7
function greet(name = "guest") {
return "Hello, " + name;
}
console.log(greet(), greet(undefined), greet(null));Vorhersagen · Aufgabe 2 von 7
function greet(name?: string): string {
return "Hello, " + name.toUpperCase();
}
console.log(greet());Üben · Aufgabe 3 von 7
function sum(____values: number[]): number {
let total = 0;
for (const v of values) total += v;
return total;
}
console.log(sum(3, 4.5, 2));Üben · Aufgabe 4 von 7
function pad(text: string, width?: number): string {
// what is width here?
return text.padStart(width ?? 8);
}Üben · Aufgabe 5 von 7
function point(x: number, y: number): string {
return "(" + x + ", " + y + ")";
}
const a = [3, 4];
const b = [3, 4] as const;
console.log(point(...a));
console.log(point(...b));Denksport · Aufgabe 6 von 7
function repeat(text: string, times = 2): string {
return text.repeat(times);
}
const counts = [undefined, 0, 3];
console.log(counts.map((n) => "[" + repeat("ab", n) + "]").join(" "));Anwenden · Aufgabe 7 von 7
Prüfen Sie Ihr Ergebnis anhand dieser Liste
Lesen Sie das ausgearbeitete Beispiel und lösen Sie dann die Übungen. Ihr Code läuft in Ihrem Browser oder auf Ihrem Computer und wird nie hochgeladen.
Ausgearbeitetes Beispiel
euro hat eine Default-Währung, line destrukturiert ein Item, dessen quantity optional ist, printReceipt und sum nehmen beliebig viele Argumente, und thanks hat einen optionalen Namen. Die letzten beiden Zeilen spreaden ein mit as const erzeugtes Tupel in eine Funktion mit zwei festen Parametern. Führen Sie npx tsc aus, dann node main.ts. Entfernen Sie danach as const und führen Sie tsc erneut aus.
main.ts
// A receipt: optional, default and rest parameters, and a destructured parameter.
type Item = { name: string; price: number; quantity?: number };
function euro(cents: number, symbol = "EUR"): string {
return (cents / 100).toFixed(2) + " " + symbol; // symbol is a string, from its default
}
function line({ name, price, quantity }: Item): string {
const count = quantity ?? 1; // quantity is number | undefined here
return (count + " x " + name).padEnd(16) + euro(price * count);
}
function sum(...amounts: number[]): number {
let total = 0;
for (const amount of amounts) total += amount;
return total;
}
function printReceipt(title: string, ...items: Item[]): void {
console.log(title);
for (const item of items) console.log(" " + line(item));
const cents = items.map((item) => item.price * (item.quantity ?? 1));
console.log(" " + "total".padEnd(16) + euro(sum(...cents)));
}
function thanks(name?: string): string {
return name === undefined ? "Thank you!" : "Thank you, " + name + "!";
}
function clock(hours: number, minutes: number): string {
return String(hours).padStart(2, "0") + ":" + String(minutes).padStart(2, "0");
}
const order: Item[] = [
{ name: "coffee", price: 320, quantity: 2 },
{ name: "croissant", price: 245 },
];
printReceipt("Cafe Mitte", ...order, { name: "water", price: 150 });
console.log(thanks());
console.log(thanks("Ada"));
const opens = [7, 30] as const; // a tuple of exactly two numbers
console.log("Open daily from " + clock(...opens));
Ausführen mit
npx tsc
node main.tsAusgabe
Cafe Mitte
2 x coffee 6.40 EUR
1 x croissant 2.45 EUR
1 x water 1.50 EUR
total 10.35 EUR
Thank you!
Thank you, Ada!
Open daily from 07:30Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.
Beim ersten Ausführen lädt Ihr Browser den TypeScript-Compiler herunter (bis zu 2.1 MB) und speichert ihn im Cache. Ihr Code bleibt auf Ihrem Gerät.
Übung 1 von 2
formatPrice(1250) soll 12.50 EUR ergeben, aber alle drei Parameter sind Pflicht, deshalb meldet tsc error TS2554: Expected 3 arguments, but got 1. Geben Sie currency den Default "EUR" und decimals den Default 2, ohne Annotationen. Fügen Sie dann einen vierten, optionalen Parameter label hinzu: Wenn er angegeben ist, beginnt das Ergebnis mit dem Label und einem Doppelpunkt, wie in Total: 12.50 EUR.
Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.
Beim ersten Ausführen lädt Ihr Browser den TypeScript-Compiler herunter (bis zu 2.1 MB) und speichert ihn im Cache. Ihr Code bleibt auf Ihrem Gerät.
Ein Default steht mit = nach dem Parameternamen, und TypeScript inferiert den Typ daraus: currency = "EUR".
Ein optionaler Parameter hat ein ? nach dem Namen und muss nach den Pflichtparametern stehen: label?: string.
Im Rumpf kann label undefined sein: return label === undefined ? text : label + ": " + text;
Ein möglicher Lösungsweg. Ihrer kann anders aussehen und trotzdem alle Prüfungen bestehen.
export function formatPrice(cents: number, currency = "EUR", decimals = 2, label?: string): string {
const text = (cents / 100).toFixed(decimals) + " " + currency;
return label === undefined ? text : label + ": " + text;
}
console.log(formatPrice(1250));
console.log(formatPrice(1999, "USD", 0));
Installieren Sie TypeScript 7.0 oder neuer. Speichern Sie diese Dateien in einem Ordner, öffnen Sie dort ein Terminal und führen Sie die Befehle unten aus.
main.ts
export function formatPrice(cents: number, currency: string, decimals: number): string {
return (cents / 100).toFixed(decimals) + " " + currency;
}
console.log(formatPrice(1250));
console.log(formatPrice(1999, "USD", 0));
main.test.ts
import {test} from 'node:test';
import assert from 'node:assert/strict';
import {formatPrice} from './main.ts';
test('formatPrice(1250) verwendet EUR und zwei Nachkommastellen', () => {
assert.equal(formatPrice(1250), '12.50 EUR', `formatPrice(1250) ergab ${JSON.stringify(formatPrice(1250))}`);
});
test('eine angegebene Währung und Stellenzahl werden verwendet', () => {
assert.equal(formatPrice(1999, 'USD', 0), '20 USD', `formatPrice(1999, 'USD', 0) ergab ${JSON.stringify(formatPrice(1999, 'USD', 0))}`);
});
test('undefined als Währung ergibt den Default', () => {
assert.equal(formatPrice(1250, undefined, 1), '12.5 EUR', `formatPrice(1250, undefined, 1) ergab ${JSON.stringify(formatPrice(1250, undefined, 1))}`);
});
test('ein Label steht vorne, mit Doppelpunkt', () => {
assert.equal(formatPrice(1250, 'EUR', 2, 'Total'), 'Total: 12.50 EUR', `formatPrice(1250, 'EUR', 2, 'Total') ergab ${JSON.stringify(formatPrice(1250, 'EUR', 2, 'Total'))}`);
});
package.json
{
"type": "module"
}
tsconfig.json
{
"compilerOptions": {
"target": "esnext",
"module": "nodenext",
"lib": [
"esnext",
"dom"
],
"types": [],
"strict": true,
"noEmit": true,
"erasableSyntaxOnly": true,
"verbatimModuleSyntax": true,
"allowImportingTsExtensions": true
},
"include": [
"**/*.ts"
],
"exclude": [
"**/*.test.ts"
]
}
npx tsc braucht TypeScript im Ordner: Führen Sie dort einmal npm install --save-dev typescript aus. tsc prüft die Typen; Node.js führt main.ts aus, indem es sie entfernt.
Programm ausführen:
npx tsc
node main.tsPrüfungen ausführen (learnrun.js muss im selben Ordner liegen):
npx tsc
node --testlearnrun.js herunterladenÜbung 2 von 2
total soll die Punkte beliebig vieler Runden addieren, einzeln übergeben: total(a, b), total() oder total(...list). describe hat keinen Parametertyp, deshalb meldet tsc error TS7006. Machen Sie rounds zu einem Rest-Parameter, und ändern Sie describe so, dass es player und points aus einer Round in seiner Parameterliste destrukturiert, mit der Annotation nach dem Muster und dem Rückgabetyp string.
Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.
Beim ersten Ausführen lädt Ihr Browser den TypeScript-Compiler herunter (bis zu 2.1 MB) und speichert ihn im Cache. Ihr Code bleibt auf Ihrem Gerät.
Ein Rest-Parameter hat drei Punkte vor dem Namen und einen Array-Typ: ...rounds: Round[].
Der Rumpf von total kann bleiben, wie er ist: rounds ist weiterhin ein Array, leer, wenn keine Runden übergeben werden.
export function describe({ player, points }: Round): string { return player + ": " + points; }
Ein möglicher Lösungsweg. Ihrer kann anders aussehen und trotzdem alle Prüfungen bestehen.
export type Round = { player: string; points: number };
export function total(...rounds: Round[]): number {
let sum = 0;
for (const round of rounds) sum += round.points;
return sum;
}
export function describe({ player, points }: Round): string {
return player + ": " + points;
}
Installieren Sie TypeScript 7.0 oder neuer. Speichern Sie diese Dateien in einem Ordner, öffnen Sie dort ein Terminal und führen Sie die Befehle unten aus.
main.ts
export type Round = { player: string; points: number };
export function total(rounds: Round[]): number {
let sum = 0;
for (const round of rounds) sum += round.points;
return sum;
}
export function describe(round) {
return round.player + ": " + round.points;
}
main.test.ts
import {test} from 'node:test';
import assert from 'node:assert/strict';
import {total, describe} from './main.ts';
const a = {player: 'Ada', points: 7};
const b = {player: 'Ada', points: 5};
test('total addiert einzeln übergebene Runden', () => {
assert.equal(total(a, b), 12, 'total(a, b) sollte 12 sein');
});
test('total() ohne Runden ist 0', () => {
assert.equal(total(), 0, 'total() sollte 0 sein');
});
test('ein Array lässt sich in total spreaden', () => {
const list = [a, b, {player: 'Grace', points: 9}];
assert.equal(total(...list), 21, 'total(...list) sollte 21 sein');
});
test('describe nennt Spieler und Punkte', () => {
assert.equal(describe(a), 'Ada: 7', `describe(a) ergab ${JSON.stringify(describe(a))}`);
});
package.json
{
"type": "module"
}
tsconfig.json
{
"compilerOptions": {
"target": "esnext",
"module": "nodenext",
"lib": [
"esnext",
"dom"
],
"types": [],
"strict": true,
"noEmit": true,
"erasableSyntaxOnly": true,
"verbatimModuleSyntax": true,
"allowImportingTsExtensions": true
},
"include": [
"**/*.ts"
],
"exclude": [
"**/*.test.ts"
]
}
npx tsc braucht TypeScript im Ordner: Führen Sie dort einmal npm install --save-dev typescript aus. tsc prüft die Typen; Node.js führt main.ts aus, indem es sie entfernt.
Programm ausführen:
npx tsc
node main.tsPrüfungen ausführen (learnrun.js muss im selben Ordner liegen):
npx tsc
node --testlearnrun.js herunterladenfunction label(prefix?: string, name: string): string {
return (prefix ?? "") + name;
}
console.log(label(undefined, "Ada"));
Was tsc oder Node.js ausgibt
main.ts(1,33): error TS1016: A required parameter cannot follow an optional parameter.Warum, und die Lösung
Argumente werden nach Position zugeordnet, also kann ein Aufrufer nicht das erste weglassen und das zweite übergeben. Stellen Sie die Pflichtparameter an den Anfang: label(name: string, prefix?: string). Muss prefix vorne bleiben, geben Sie ihm stattdessen einen Default (prefix = ""), und Aufrufer übergeben undefined, um ihn zu nutzen.
function area({ width: number, height: number }) {
return width * height;
}
console.log(area({ width: 3, height: 4 }));
Was tsc oder Node.js ausgibt
main.ts(1,24): error TS2300: Duplicate identifier 'number'.Warum, und die Lösung
In einem Destrukturierungsmuster bedeutet width: number "nimm width und nenne die Variable number", also gibt es zwei Variablen namens number und keine namens width. Die Annotation steht nach dem ganzen Muster: function area({ width, height }: { width: number; height: number }).
function myForEach(arr: number[], callback: (arg: number, index?: number) => void) {
for (let i = 0; i < arr.length; i++) {
callback(arr[i], i);
}
}
myForEach([1, 2, 3], (a, i) => {
console.log(i.toFixed());
});
Was tsc oder Node.js ausgibt
main.ts(8,15): error TS18048: 'i' is possibly 'undefined'.Warum, und die Lösung
index?: number sagt, dass myForEach den Callback auch ohne Index aufrufen könnte, also muss jeder Callback mit undefined rechnen, obwohl die Schleife immer einen übergibt. Folgen Sie der Regel des Handbooks und schreiben Sie index: number. Callbacks, die ihn nicht brauchen, wie (a) => console.log(a), passen trotzdem.
TypeScript im Browser: der Compiler von TypeScript 6.0.3, Apache-2.0, danach die eigene Engine Ihres Browsers. Lizenz und Quellcode
5 Fragen, ohne Hinweise. Ab 80 % ist die Lektion abgeschlossen.
Erledigen Sie zuerst alle Aufgaben oben, um das Abschlussquiz freizuschalten.