Generika in TypeScript

Generika in TypeScript

Dieser Artikel erklärt Generika in TypeScript.

YouTube Video

Generika in TypeScript

Generika in TypeScript sind eine Funktion, die es ermöglicht, wiederverwendbare und typsichere Funktionen, Klassen und Schnittstellen durch Parametrisierung von Typen zu definieren. Durch die Verwendung von Generika können Sie Code schreiben, der nicht von spezifischen Typen abhängt, sodass Sie die gleichen Operationen auf verschiedenen Typen ausführen können.

Grundlagen der Generika

Generika funktionieren wie Vorlagen, die Typen als Argumente akzeptieren und es Funktionen und Klassen ermöglichen, verschiedene Typen zu verarbeiten.

Generische Funktionen

Das Folgende ist ein Beispiel für eine Funktion, deren Argumenttypen mithilfe von Generika angegeben sind.

1function identity<T>(value: T): T {
2    return value;
3}
4
5console.log(identity<number>(42));       // 42
6console.log(identity<string>("Hello"));  // Hello
  • T ist ein generisches Typ-Argument, das die Typen der Argumente und des Rückgabewerts der Funktion repräsentiert. Der tatsächliche Typ wird bestimmt, wenn die Funktion aufgerufen wird.
  • Indem Sie explizit <number> oder <string> angeben, legen Sie den Typ fest.

Generische Typen funktionieren auch ohne explizite Angabe, da TypeScript eine Typinferenz durchführt.

1function identity<T>(value: T): T {
2    return value;
3}
4
5console.log(identity(42));       // 42
6console.log(identity("Hello"));  // Hello

Einschränkungen für Generika

Durch Einschränkungen für Generika können Sie sie darauf beschränken, nur bestimmte Typen zu akzeptieren.

1function loggingIdentity<T extends { length: number }>(arg: T): T {
2    console.log(arg.length);
3    return arg;
4}
5
6loggingIdentity("Hello");  // 5
7loggingIdentity([1, 2, 3]);  // 3
8
9// loggingIdentity(42);  // Error: number does not have a length property.
  • Die Angabe T extends { length: number } zeigt an, dass T ein Typ mit einer length-Eigenschaft sein muss. Daher werden Typen ohne eine length-Eigenschaft nicht akzeptiert.

Generische Klassen

Klassen können ebenfalls mit Generika definiert werden. Generische Klassen bieten flexible Typen für Eigenschaften und Methoden.

 1class Box<T> {
 2    private _value: T;
 3
 4    constructor(value: T) {
 5        this._value = value;
 6    }
 7
 8    public getValue(): T {
 9        return this._value;
10    }
11
12    public setValue(value: T): void {
13        this._value = value;
14    }
15}
16
17const numberBox = new Box<number>(100);
18console.log(numberBox.getValue());  // 100
19
20const stringBox = new Box<string>("Hello");
21console.log(stringBox.getValue());  // Hello
  • Box<T> deklariert den Typ T, der innerhalb der Klasse als generischer Typ verwendet wird. Dadurch kann dieselbe Klasse für verschiedene Typen wiederverwendet werden.

Generische Schnittstellen

Generika können auch mit Schnittstellen verwendet werden.

 1interface Pair<T, U> {
 2    first: T;
 3    second: U;
 4}
 5
 6const numberStringPair: Pair<number, string> = { first: 1, second: "One" };
 7console.log(numberStringPair);  // { first: 1, second: 'One' }
 8
 9const booleanArrayPair: Pair<boolean, number[]> = { first: true, second: [1, 2, 3] };
10console.log(booleanArrayPair);  // { first: true, second: [ 1, 2, 3 ] }
  • Durch die Angabe von zwei generischen Typen mit Pair<T, U> können Sie ein Objekt mit einer Kombination aus verschiedenen Typen definieren.

Standardtypargumente

Es ist auch möglich, einen Standardtyp für generische Typargumente anzugeben.

1function createArray<T = string>(length: number, value: T): T[] {
2    return Array(length).fill(value);
3}
4
5console.log(createArray(3, "a"));   // ['a', 'a', 'a']
6console.log(createArray(3, 100));   // [100, 100, 100]
  • Wir setzen das Standardtypargument mit <T = string> auf string. Wenn kein Typ explizit angegeben wird, ist T vom Typ string.

Generische Typalias

Generika können auch als Typalias (type) verwendet werden.

 1type Result<T> = {
 2    success: boolean;
 3    data: T;
 4};
 5
 6const successResult: Result<number> = { success: true, data: 42 };
 7const errorResult: Result<string> = { success: false, data: "Error occurred" };
 8
 9console.log(successResult);  // { success: true, data: 42 }
10console.log(errorResult);    // { success: false, data: 'Error occurred' }
  • Result<T> steht für ein Ergebnisobjekt, das Daten vom Typ T enthält. Auf diese Weise können Sie flexible Typalias mit Generika erstellen.

Mehrere generische Typen

Durch die Verwendung mehrerer generischer Typen können Sie noch vielseitigere Funktionen und Klassen definieren.

1function merge<T, U>(obj1: T, obj2: U): T & U {
2    return { ...obj1, ...obj2 };
3}
4
5const person = { name: "Alice" };
6const job = { title: "Engineer" };
7
8const merged = merge(person, job);
9console.log(merged);  // { name: 'Alice', title: 'Engineer' }
  • Die Funktion merge nimmt zwei verschiedene Typen T und U und kombiniert sie, um ein neues Objekt zurückzugeben.

Zusammenfassung

  • Generika ermöglichen wiederverwendbaren und typsicheren Code, indem sie Typen als Parameter behandeln.
  • Durch die Verwendung von Generika in Funktionen, Klassen und Schnittstellen können Sie flexible Logik schreiben, die verschiedene Typen verarbeitet.
  • Durch das Hinzufügen von Einschränkungen zu Typargumenten oder das Festlegen von Standardtypargumenten können Sie den Geltungsbereich von Generika steuern.

Mit Generika können Sie typenunabhängigen, universellen Code schreiben und die Vorteile des leistungsstarken Typsystems von TypeScript nutzen.

Sie können den obigen Artikel mit Visual Studio Code auf unserem YouTube-Kanal verfolgen. Bitte schauen Sie sich auch den YouTube-Kanal an.

YouTube Video