Lösung:
function sum(a: number, b: number): number {
return a + b;
}
console.log(sum(5, 3)); // Ausgabe: 8Auto, die
Eigenschaften marke (String) und modell
(String) hat. Fügen Sie einen Konstruktor hinzu, um diese Eigenschaften
zu initialisieren, und eine Methode getAutoInfo, die eine
Zeichenkette mit den Informationen des Autos zurückgibt.Lösung:
class Auto {
constructor(private marke: string, private modell: string) {}
getAutoInfo(): string {
return `Marke: ${this.marke}, Modell: ${this.modell}`;
}
}
const auto = new Auto('BMW', 'X3');
// Ausgabe: "Marke: BMW, Modell: X3"
console.log(auto.getAutoInfo());identity, die einen Parameter jeglichen Typs akzeptiert und
denselben Wert zurückgibt.Lösung:
function identity<T>(arg: T): T {
return arg;
}
// Ausgabe: "hello"
console.log(identity('hello'));
// Ausgabe: 42
console.log(identity(42));Person mit den
Eigenschaften name und alter. Erstellen Sie
dann ein Objekt, das dieses Interface implementiert.Lösung:
interface Person {
name: string;
alter: number;
}
const person: Person = {
name: 'John',
alter: 30
};
// Ausgabe: { name: 'John', alter: 30 }
console.log(person);Lösung:
function sortNumbers(numbers: number[]): number[] {
return numbers.sort((a, b) => a - b);
}
// Ausgabe: [1, 3, 5, 6, 9]
console.log(sortNumbers([5, 3, 9, 1, 6]));Lösung:
enum Wochentag {
Montag,
Dienstag,
Mittwoch,
Donnerstag,
Freitag,
Samstag,
Sonntag
}
// Ausgabe: 5
console.log(Wochentag.Samstag);applyOperation, die zwei
Zahlen und eine Funktion akzeptiert. Die Funktion sollte die beiden
Zahlen als Parameter an die übergebene Funktion übergeben und das
Ergebnis zurückgeben. Testen Sie applyOperation mit einer
Funktion, die die Summe von zwei Zahlen berechnet, und einer Funktion,
die die Differenz zwischen zwei Zahlen berechnet.Lösung:
// Typendefinition für eine Funktion, die zwei Zahlen akzeptiert
// und eine Zahl zurückgibt
type NumberOperation = (a: number, b: number) => number;
function applyOperation(a: number, b: number, operation: NumberOperation): number {
return operation(a, b);
}
// Lambda-Ausdrücke für Summe und Differenz
let sum: NumberOperation = (a, b) => a + b;
let difference: NumberOperation = (a, b) => a - b;
// Ausgabe: 8
console.log(applyOperation(5, 3, sum));
// Ausgabe: 2
console.log(applyOperation(5, 3, difference));In diesem Beispiel ist NumberOperation ein Typ, der für
eine Funktion steht, die zwei Zahlen als Parameter akzeptiert und eine
Zahl zurückgibt. Die Funktion applyOperation verwendet
diesen Typ für ihren operation-Parameter, so dass Sie eine
Funktion übergeben können, die dieser Signatur entspricht. Die
sum und difference Funktionen sind
Lambda-Ausdrücke, die diese Signatur erfüllen, und können daher an
applyOperation übergeben werden.
pruefeKlammerung, die einen
String als Parameter akzeptiert und überprüft, ob alle öffnenden
Klammern korrekt geschlossen werden. Die Funktion sollte
true zurückgeben, wenn die Klammerung korrekt ist, und
false sonst.Lösung:
function pruefeKlammerung(input: string): boolean {
let klammerCounter = 0;
for (let char of input) {
if (char === '(') {
klammerCounter++;
} else if (char === ')') {
klammerCounter--;
if (klammerCounter < 0) {
// Schließende Klammer ohne passende öffnende Klammer gefunden
return false;
}
}
}
// Klammerung ist korrekt, wenn alle öffnenden Klammern geschlossen wurden
return klammerCounter === 0;
}
// Ausgabe: true
console.log(pruefeKlammerung('2*(a+5)'));
// Ausgabe: false
console.log(pruefeKlammerung('2*)5+a('));
// Ausgabe: false
console.log(pruefeKlammerung('2*(5+a'));In dieser Lösung durchläuft die Funktion
pruefeKlammerung jeden Charakter im Eingabestring. Wenn sie
eine öffnende Klammer findet, erhöht sie einen Zähler. Wenn sie eine
schließende Klammer findet, verringert sie den Zähler. Wenn der Zähler
zu irgendeinem Zeitpunkt negativ wird (was bedeutet, dass eine
schließende Klammer gefunden wurde, bevor eine entsprechende öffnende
Klammer gefunden wurde), gibt die Funktion sofort false
zurück. Am Ende der Funktion überprüft sie, ob der Zähler null ist (was
bedeutet, dass jede geöffnete Klammer geschlossen wurde), und gibt das
Ergebnis zurück.
Lösung per Rekursion:
function pruefeKlammerung(input: string, index = 0, count = 0): boolean {
if (count < 0) {
// Schließende Klammer ohne passende öffnende Klammer gefunden
return false;
}
if (index === input.length) {
// Alle Zeichen durchlaufen, überprüfen, ob
// alle öffnenden Klammern geschlossen wurden
return count === 0;
}
if (input[index] === '(') {
count++;
} else if (input[index] === ')') {
count--;
}
return pruefeKlammerung(input, index + 1, count);
}
// Ausgabe: true
console.log(pruefeKlammerung('2*(a+5)'));
// Ausgabe: false
console.log(pruefeKlammerung('2*)5+a('));
// Ausgabe: false
console.log(pruefeKlammerung('2*(5+a'));In dieser Lösung durchläuft die Funktion
pruefeKlammerung rekursiv jeden Charakter im Eingabestring.
Der Basisfall für die Rekursion ist, wenn alle Zeichen durchlaufen
wurden (index === input.length), dann gibt die Funktion
true zurück, wenn alle geöffneten Klammern geschlossen
wurden (d.h., count === 0), und false sonst.
Wenn der Zähler zu irgendeinem Zeitpunkt negativ wird (was bedeutet,
dass eine schließende Klammer gefunden wurde, bevor eine entsprechende
öffnende Klammer gefunden wurde), gibt die Funktion sofort
false zurück.
Vereinfachte Lösung per Rekursion:
function pruefeKlammerung(input: string, count = 0): boolean {
if (count < 0 || (input.length === 0 && count !== 0)) {
// Schließende Klammer ohne passende öffnende Klammer
// gefunden oder am Ende nicht alle Klammern geschlossen
return false;
}
if (input.length === 0 && count === 0) {
// Alle Zeichen durchlaufen, alle öffnenden Klammern
// wurden geschlossen
return true;
}
const firstChar = input[0];
const restString = input.slice(1);
if (firstChar === '(') {
return pruefeKlammerung(restString, count + 1);
} else if (firstChar === ')') {
return pruefeKlammerung(restString, count - 1);
} else {
return pruefeKlammerung(restString, count);
}
}
// Ausgabe: true
console.log(pruefeKlammerung('2*(a+5)'));
// Ausgabe: false
console.log(pruefeKlammerung('2*)5+a('));
// Ausgabe: false
console.log(pruefeKlammerung('2*(5+a'));In dieser überarbeiteten Version wird der aktuelle String in
firstChar (das erste Zeichen des aktuellen Strings) und
restString (der Rest des Strings ohne das erste Zeichen)
aufgeteilt. Dann wird firstChar überprüft und
restString zusammen mit dem aktualisierten Zähler
count an die nächste Rekursionsebene übergeben. Diese
Strategie macht den Code einfacher und leichter zu verstehen, da sie
keine separate Indexvariable benötigt.
Aufgabe 9: Implementieren Sie eine generische
SafeArray<T> Klasse in TypeScript, die nur Elemente
vom Typ T aufnehmen kann. Die Klasse sollte die Methoden
push, pop, get und
size enthalten. Implementieren Sie zusätzlich eine Methode
isEmpty, die true zurückgibt, wenn das Array
leer ist und false sonst.
class SafeArray<T> {
private elements: T[] = [];
push(element: T): void {
this.elements.push(element);
}
pop(): T | undefined {
return this.elements.pop();
}
get(index: number): T | undefined {
return this.elements[index];
}
size(): number {
return this.elements.length;
}
isEmpty(): boolean {
return this.size() === 0;
}
}Aufgabe 10: Erstellen Sie eine TypeScript-Funktion
flatten, die ein verschachteltes Array beliebiger Tiefe
(also ein Array, das andere Arrays enthalten kann, die wiederum andere
Arrays enthalten können, usw.) nimmt und ein flaches Array zurückgibt,
das alle Elemente des Eingabe-Arrays in der gleichen Reihenfolge
enthält.
function flatten(input: any[]): any[] {
return input.reduce((accumulator, current) =>
accumulator.concat(Array.isArray(current)
? flatten(current) : current), []);
}Aufgabe 11: Implementieren Sie in TypeScript das
Observer Pattern. Erstellen Sie eine Subject-Klasse mit den
Methoden registerObserver, unregisterObserver
und notifyObservers. Implementieren Sie auch eine
Observer-Interface mit einer
update-Methode.
interface Observer {
update(): void;
}
class Subject {
private observers: Observer[] = [];
registerObserver(observer: Observer): void {
this.observers.push(observer);
}
unregisterObserver(observer: Observer): void {
const observerIndex = this.observers.indexOf(observer);
if (observerIndex > -1) {
this.observers.splice(observerIndex, 1);
}
}
notifyObservers(): void {
for (let observer of this.observers) {
observer.update();
}
}
}Aufgabe 12: Implementieren Sie eine Funktion
pipe, die eine Liste von Funktionen akzeptiert und eine
Funktion zurückgibt, die, wenn sie aufgerufen wird, die Ausgabe jeder
Funktion in der Liste als Eingabe für die nächste Funktion
verwendet.
function pipe(functions: Function[]): Function {
return function(input: any) {
return functions.reduce((accumulator, currentFunction) => currentFunction(accumulator), input);
}
}Aufgabe 13: Implementieren Sie eine generische
Queue<T> Klasse in TypeScript, die die Methoden
enqueue, dequeue und size
enthält. enqueue sollte ein Element zur Queue hinzufügen,
dequeue sollte das älteste Element entfernen und
zurückgeben, und size sollte die Anzahl der Elemente in der
Queue zurückgeben.
class Queue<T> {
private elements: T[] = [];
enqueue(element: T): void {
this.elements.push(element);
}
dequeue(): T | undefined {
return this.elements.shift();
}
size(): number {
return this.elements.length;
}
}Aufgabe 14: Implementieren Sie eine Funktion
deepEqual, die zwei Objekte als Eingabe nimmt und
true zurückgibt, wenn sie strukturell identisch sind, und
false sonst.
function deepEqual(object1: any, object2: any): boolean {
if (object1 === object2) {
return true;
}
if (typeof object1 !== 'object' || object1 === null || typeof object2 !== 'object' || object2 === null) {
return false;
}
let keys1 = Object.keys(object1);
let keys2 = Object.keys(object2);
if (keys1.length !== keys2.length) {
return false;
}
for (let key of keys1) {
if (!keys2.includes(key) || !deepEqual(object1[key], object2[key])) {
return false;
}
}
return true;
}